事务指满足ACID特性的一组操作,可以通过Commit提交,Rollback回滚
一.ACID
1.Atomicity原子性
事务是不可分割的最小单元,事务的所有操作要么全部提交成功,要么全部失败回滚。
回滚时根据日志反向操作
2.Consistency一致性
事务执行前后保持一致性状态,所有事务对一个数据的读取结果都是相同的。
例如:转账前A账户有3000,B账户有2000,无论怎么转,A+B账户都只有5000
3.Isolation隔性
一个事务所做的修改在最终提交之前,对其他事务是不可见的
4.Durability持久性
一旦事务提交,则所做的修改会永远保存到数据库中。使用日志来保证持久性,应对数据库崩溃
ACID的关系:
1.满足了一致性,事务的执行结果才是正确的
2.无并发时,事务串行执行,满足隔离性,此时只要满足原子性就能保证一致性
3.有并发时,事务并行执行,事务要同时满足原子性和隔离型才能保证一致性
4.持久性是为了应对数据库崩溃的情况
二.隔离性引发的问题
并发环境下,事务的隔离性难以保证,会引发一致性的问题
1.丢失修改:a的修改被b覆盖
2.脏读:b读取到了a修改的数据,但是a撤销了这次修改,b读到的就是脏数据
3.不可重复读:a两次分别读到了b修改前后的同一个数据,读到了两个结果
4.虚读(幻读):a读取某个范围的数据(count),b在这个范围内插入新数据,a再读时的结果就不一样了
通过锁来保护隔离性。锁不用用户控制,数据库提供了事务的隔离级别
三.锁
mysql中提供了两种锁的粒度:行级锁和表级锁
选择锁的粒度要权衡锁开销和并发程度
1.锁类型
1)读写锁:
写锁——X锁
读锁——S锁
- 一个事务对数据对象 A 加了 X 锁,就可以对 A 进行读取和更新。加锁期间其它事务不能对 A 加任何锁。
- 一个事务对数据对象 A 加了 S 锁,可以对 A 进行读取操作,但是不能进行更新操作。加锁期间其它事务能对 A 加 S 锁,但是不能加 X 锁。
2)意向锁:
意向锁在原来的 X/S 锁之上引入了 IX/IS,IX/IS 都是表锁,用来表示一个事务想要在表中的某个数据行上加 X 锁或 S 锁。有以下两个规定:
- 一个事务在获得某个数据行对象的 S 锁之前,必须先获得表的 IS 锁或者更强的锁;
- 一个事务在获得某个数据行对象的 X 锁之前,必须先获得表的 IX 锁。
通过引入意向锁,事务 T 想要对表 A 加 X 锁,只需要先检测是否有其它事务对表 A 加了 X/IX/S/IS 锁,如果加了就表示有其它事务正在使用这个表或者表中某一行的锁,因此事务 T 加 X 锁失败。
2.三级锁协议解决隔离性引发的问题:
1)一级锁协议:事务T要修改数据A时必须要加X锁,T结束时才释放锁
可以解决丢失修改的问题,一个没写完之前另一个只能等
2)二级锁协议:在一级的基础上,再要求读取数据A时必须加S锁,读取完后马上释放S锁
可以解决脏读(读未提交)的问题,因为一个事务在写的时候加了X锁,而加了X锁期间不能再加任何锁,
在加S锁的时候肯定是释放了X锁(写完毕),所以不会读到未提交的数据。
3)三级锁协议:在二级的基础上,要求读取A时必须加S锁,事务结束了才能释放S锁
二级是读取完了就释放S锁,这个是事务结束了才释放S锁,因此解决了不可重复读的问题。
3.两段锁协议:加锁和解锁分为两个阶段进行
可串行化调度:通过并发控制,使并发执行的事务结果看起来像串行执行的事务
两段锁协议是保证可串行化的充分条件
mysql的InnoDB引擎采用两段锁协议
四.事务隔离级别
1.未提交读
事务中的修改,即使没有提交,也对其他事务可见
2.提交读
一个事务只能读取已经提交的事务所做的修改,即在修改的事务对其他事务不可见(二级锁协议)
3.可重复读
保证一个事务多次读取同样的结果是一样的(三级锁协议)
4.可串行化
强制事务串行执行
五.总结
1.事务是一次操作的最小单位——>事务的四个特性:A原子性,C一致性,I隔离性,D持久性——>四个特性的关系
2.事务的隔离性引发的问题:丢失修改,脏读,不可重复度,虚读——>引入锁解决隔离性的问题——>读写锁,意向锁——>
引入锁协议:三级锁协议与两段锁协;对应事务的隔离级别:即读未提交,读已提交,可重复读,串行化
摘自: