MySql MVCC是如何实现的-事务隔离级别?

事务就是要保证一组数据库操作,要么全部成功,要么全部失败。
在MySql中,事务支持是在引擎层实现的,但是只有InnoDB支持事务,MyISAM是不支持的。
事务具有原子性,一致性,隔离性,持久性,这里我们要谈的就是隔离性。
MySql标准的事务隔离级别包括:
读未提交(read uncomminted):一个事务还没有提交时,它做的变更就能被被的事务看到。
读提交(read commited):一个事务提交后,它做的变更才会被其他事务看到。
可重复读(repeatable read):一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。
串行化(serializable):对于同一行记录,“写”会加“写锁”,“读”会加“读锁”,出现读写锁冲突的时候,后访问的食物必须等待前一个事务执行完成,才能继续执行。

事务隔离级别 脏读 不可重复读 幻读
读未提交
不可重复读
可重复读
串行化

1.查看MySql默认的隔离级别,可见MySql默认可重复读。从上图我们可以看到,不管是什么隔离级别,都会存在一些问题,并且隔离的越严实,执行效率就会越低。比如:串行化,所以很多时候我们只是在效率和隔离之间找一个平衡点。

MySql5.7以前的版本:show variables like 'tx_isolation';
MySql5.7(包含)以后的版本:show variables like 'transaction_isolation';

mysql> show variables like 'tx_isolation';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)

举例说明:

事务A 事务B
1启动事务
2.查询得到值V0 3启动事务
4.查询得到值V0
5.将V0改为V0+1
6.查询得到值V1
7.提交事务B
8.查询得到值V2
9.提交事务A
10.查询得到值V3

1.读未提交

  • 将会话的隔离级别设置为读未提交,终端1和终端2一起设置
set session transaction isolation level read uncommitted;
  • 按照上述表格中的顺序,依次执行,得到V0=1,V1=2,V2=2,V3=2

注意步骤6直接读到了步骤5中修改的值,此时事务B实际还未提交,这就是读未提交(read uncommited),事务级别读未提交存在脏读的问题,比如此用例中如果事务B做了回滚,那么事务A在第4步骤查询得到的值就是不正确的,这就是所谓的脏读

2.读提交

  • 将会话的隔离级别设置为读提交,终端1和终端2一起设置
set session transaction isolation level read committed;
  • 按照上述表格中的顺序,依次执行,得到V0=2,V1=2,V2=3,V3=3

注意步骤6没有读到步骤5中修改的值,步骤7,事务B提交之后,步骤8读到了步骤5修改的值,这就是读提交(read commited),事务级别读提交存在不可重复读的问题,比如此用例中,同一个事务,在不同的阶段读同一行数据读到了不同的值,这就是所谓的不可重复读,解决不可重复读的方法是加行锁,事务A在执行未提交的时候,事务B无法修改数据,即可避免

3.可重复读

  • 将会话的隔离级别设置为可重复读,终端1和终端2一起设置
set session transaction isolation level repeatable read;
  • 按照上述表格中的顺序,依次执行,得到V0=3,V1=3,V2=3,V3=4

注意步骤6没有读到步骤5中更改的值,步骤7事务B提交之后,步骤8依然没有读到步骤5中更改的值,直到事务A也提交之后才读到事务B更改的值,这就是可重复读(repeatable read)

  • 事务级别可重复读存在幻读的问题
事务A 事务B
1启动事务
2查询V0
3插入
4查询V1
5提交事务
6查询V2
7更新
8查询V3
  • 按照上述表格的顺序,依次执行,V0=V1=V2=5行,V3=6行,也就是在事务A中查到事务B插入的数据,这就是所谓的幻读,解决幻读的方法是加表锁,事务A在执行未提交的时候,事务B无法插入数据,即可避免

4.串行化

  • 将会话的隔离级别设置为串行化,终端1和终端2一起设置
set session transaction isolation level serializable;
事务A 事务B
1启动事务
2启动事务
3插入数据
4查询数据
5提交事务
6查询数据

按照上述表格的顺序,依次执行,步骤3插入数据,但是未提交的时候,步骤4出现了获取锁超时的情况,这就是串行化(serializable
,同一行数据不允许并发执行,在写时,读必须等待。

牛人之所以是牛人,是因为你现在在踩的坑,他曾经都已经踩过了。
原文地址:https://www.cnblogs.com/dwBurning/p/mvcctransaction.html