简述事务
事务内的语句要么全部执行成功,要么全部执行失败。
事务满足如下几个特性:
原子性(Atomicity):一个事务中的所有操作要么全部完成,要么全部不完成。
一致性(Consistency):事务执行前后数据库的状态保存一致。
隔离性(Isolation):多个并发事务对数据库进行操作,事务间互不干扰。
持久性(Durability):事务执行完毕,对数据的修改是永久的,即使系统故障也不会丢失
数据库中多个事务同时进行可能会出现什么问题?
丢失修改
脏读:当前事务可以查看到别的事务未提交的数据。
不可重读:在同一事务中,使用相同的查询语句,同一数据资源莫名改变了。
幻读:在同一事务中,使用相同的查询语句,莫名多出了一些之前不存在的数据,或莫名少了一些
原先存在的数据。
SQL的事务隔离级别有哪些?
读未提交:
一个事务还没提交,它做的变更就能被别的事务看到。
读提交:一个事务提交后,它做的变更才能被别的事务看到。
可重复读:
一个事务执行过程中看到的数据总是和事务启动时看到的数据是一致的。在这个级别下事务未
提交,做出的变更其它事务也看不到。
串行化:
对于同一行记录进行读写会分别加读写锁,当发生读写锁冲突,后面执行的事务需等前面执行
的事务完成才能继续执行。
什么是MVCC?
MVCC为多版本并发控制,即同一条记录在系统中存在多个版本。其存在目的是在保证数据一致性的前提下提供一种高并发的访问性能。对数据读写在不加读写锁的情况下实现互不干扰,从而实现数据库的隔离性,在事务隔离级别为读提交和可重复读中使用到。
在InnoDB中,事务在开始前会向事务系统申请一个事务ID,该ID是按申请顺序严格递增的。每行数据具有多个版本,每次事务更新数据都会生成新的数据版本,而不会直接覆盖旧的数据版本。数据的行结构中包含多个信息字段。其中实现MVCC的主要涉及最近更改该行数据的事务ID(DB_TRX_ID)和可以找到历史数据版本的指针(DB_ROLL_PTR)。InnoDB在每个事务开启瞬间会为其构造一个记录当前已经开启但未提交的事务ID的视图数组。通过比较链表中的事务ID与该行数据的值与对应的
DB_TRX_ID,并通过DB_ROLL_PTR找到历史数据的值以及对应的DB_TRX_ID来决定当前版本的数据是否应该被当前事务所见。最终实现在不加锁的情况下保证数据的一致性。
读提交和可重复读都基于MVCC实现,有什么区别?
在可重复读级别下,只会在事务开始前创建视图,事务中后续的查询共用一个视图。而读提交级别下每 个语句执行前都会创建新的视图。因此对于可重复读,查询只能看到事务创建前就已经提交的数据。而 对于读提交,查询能看到每个语句启动前已经提交的数据。
InnoDB如何保证事务的原子性、持久性和一致性?
利用undo log保障原子性。该log保存了事务发生之前的数据的一个版本,可以用于回滚,从而保证事务 原子性。
利用redo log保证事务的持久性,该log关注于事务的恢复.在重启mysql服务的时候,根据redo log进行 重做,从而使事务有持久性。
利用undo log+redo log保障一致性。事务中的执行需要redo log,如果执行失败,需要undo log 回滚。
事务的分类
事务分为隐式事务和显式事务两种。我们的DML语句(insert、update、delete)就是隐式事务。
隐式事务:该事务没有明显的开启和结束标记,它们都具有自动提交事务的功能;不妨思考一下,update语句修改数据时,是不是对表中数据进行改变了,它的本质其实就相当于一个事务。
显示事务:该事务具有明显的开启和结束标记;也是本文重点要讲的东西。使用显式事务的前提是你得先把自动提交事务的功能给禁用。禁用自动提交功能就是设置autocommit变量值为0(0:禁用 1:开启)
开启事务的步骤
#步骤一:开启事务(可选)
start transaction;
#步骤二:编写事务中的sql语句(insert、update、delete)
#这里实现一下"李二给王五转账"的事务过程
update t_account set balance = 50 where vname = "李二";
update t_account set balance = 130 where vname = "王五";
#步骤三:结束事务
commit; #提交事务
# rollback; #回滚事务:就是事务不执行,回滚到事务执行前的状态