MySql事务实现原理--参考极客时间专栏《MySQL实战45讲》,博客
1.事务的基本要素(ACID)
原子性(Atomicity):事务内的操作要嘛全部完成,要嘛全部回滚。
一致性(Consistency):事务执行的前后都是合法的数据状态,不会违反任何的数据完整性。
隔离性(Isolation):主要是事务之间的相互的影响,根据隔离有不同的影响效果。
持久性(Durability):事务一旦提交,就会体现在数据库上,不能回滚。
2.事务并发的问题
脏读:比如事务A执行的过程中,读到了事务B未提交的内容。
不可重复度:指一个事务在前后两次查询的结果不一致。
幻读:幻读是指前后两次相同条件下的查询,后一次查询读到了前一次查询没有的行数据。
特别注意的是:在不可重复读的隔离级别下,普通查询是不会出现幻读的,因为都是快照读,只有在当前读,也就是select语句后面加for update查询的时候出现,幻读的解决办法,后面会有。
3.事务的隔离级别
(1)读未提交
存在问题:脏读,不可重复读,幻读。
(2)读已提交
存在问题:不可重复读,幻读.
实现依赖于一致性视图(MVCC实现):查询只承认在语句启动前就已经提交完成的数据。
(3)可重复读
存在问题:幻读,使用当前读解决读已提交隔离级别的不可重复读。
实现依赖于一致性视图(MVCC实现):查询只承认在事务启动前就已经提交完成的数据;
幻读的问题:
1.破坏语义
select * from test_table where col_1 = 1 for update;
这条sql语句的本意是要把test_table的col_1 为1的行锁住,不允许别人事务对这些行进行操作。
假设test_table中id为1的行,col_1的值不为1
有以下两个语句:
update test_table set col_1 = 1 where id = 1
update test_table set col_2 = 12 where id = 1
对test_table的col_1 为1的行进行修改,违背了将这些行锁住的语句。
2.数据一致性问题
主要体现在各个事务提交的时间点不确定,各个事务之间的语句会有影响,从而写到binlog的逻辑语句与表达的语义不一致。
即使对所有的行加入了锁,也会出现不一致,因为可能要插入心的行。
幻读解决办法:
引入间隙锁,会锁住区间,跟间隙锁存在冲突关系的,是“往这个间隙中插入一个记录”这个操作。间隙锁和行锁合称 next-key lock。
间隙锁的困扰:有可能引发死锁。主要体现在两个事务互相等待对方的间隙锁。
解决办法:隔离级别设为读已提交,同时为了解决数据不一致问题,binlog的格式设置为row。
选择哪一个事务隔离级别,具体问题具体分析。
(4)串行化
存在问题:没有幻读,脏读,不可重复读的问题,但是由于是串行,性能非常差。