ACID、MVCC、隔离级别
一、事务的ACID:
1、Atomic:原子性
多条SQL执行,要么一起成功,要么一起失败,执行状态保持一致。
2、Consistency:一致性
一组SQL执行之前,数据必须是准确的,执行之后,数据也必须是准确的。
必须符合逻辑计算。
3、Isolation:隔离性
多个事务在执行的时候不能互相干扰。
4、Durability:持久性
事务成功之后,对数据的修改是永久有效的。
二、事务隔离级别
1、读未提交--脏读,Read Uncommitted:
事务A修改的数据还没提交的时候,就被事务B给读到了,也就是脏读。
2、读已提交--不可重复读,Read Committed:
事务A先查询,然后事务B修改这条数据并且提交了,此时事务A再次查询数据不一样,所以是读已提交。
特指一个事务内对一个数据两次读,可能会读到不一样的值。
3、可重复读--幻读,Read Repeatable:
事务A在执行过程中,查询的这行数据肯定不会发生变化。
此时事务B插入一条数据,事务A本来查询到1条,现在突然看到两条,好像出现幻觉一样。
特指的是多次查询读到的行数不同。
MySQL默认事务隔离级别就是可重复读。
4、串行化:Seriaizable
如果要解决幻读,就需要使用串行化级别的隔离级别,所有事务都串行起来,不允许多个事务并行操作。
5、不可重复读和幻读的区别:
不可重复读针对的是修改,而幻读对应的是数据被删除或者新增。
三、MySQL默认事务隔离级别:
默认可重复读,可以避免脏读和不可重复读,但是可能出现幻读,但是MySQL同样可以避免幻读。
四、MySQL如何实现可重复读?
MySQL是通过MVCC机制来实现的,multi-version concurrency control。
innodb存储引擎,会在每行数据的最后加两个隐藏列,保存行的事务id和当前操作行的事务id,事务id是mysql自己维护的自增的,全局唯一。
id | name | 创建事务id | 删除事务id |
---|---|---|---|
1 | Sam | 120 | 122 |
2 | Jason | 119 | 122 |
2 | James | 122 | null |
删除对应的事务id,要么没有,那么肯定比当前事务id大(当前开启事务之后才会删除)。
查询一行数据,创建事务id <= 当前事务id <= 删除事务id,满足上面两个条件的数据才会被查出来。
1、如果事务id = 121的查询id = 1的这行数据,是可以查到的。
2、事务id = 122把id = 1的数据删除。
3、事务id = 121查询id = 1肯定还是可以查到的。
4、事务id = 122将id = 2的name从Jason修改成James,实际上是创建一个新的数据,id不变,创建事务id为122。
5、事务id = 121 查询id = 2的那行数据,name还是Jason的,因为小于122。
更新操作:
事务执行期间,别的事务更新了一条数据呢?
在innodb中,更新是插入了一行记录,然后将新插入的记录的创建事务ID设置为新的事务的id,同时将这条记录之前的那个版本的删除事务ID设置为新的事务的id。