Mysql事务分析(1)

215 阅读2分钟

数据库在事务并发执行的时候可能产生脏写、脏读、不可重复读、幻读几种问题。为了解决这些问题SQL标准中制定了几种隔离级别。注意一下这里并不是说的Mysql里的隔离级别,说得是SQL标准中怎么规定的事务隔离级别。

  1. read uncommitted (读未提交)
  2. read committed(读已提交)
  3. repeatable read(可重复读)
  4. serializable(串行化)

在read uncommitted 隔离级别下不会发生脏写的情况,因为不可能让两个事务在未提交的情况下去更新通一行数据。但是会发生脏读、不可重复读、幻读 在read committed 隔离级别下不会发生脏读的情况,也就是说其他事务在未提交的情况下你是读不到的。 在repeatable read 隔离级别下不会发生脏写、脏读、不可重复读的情况,事务一旦开启多次读取一个数据的值一定是一样的。但是还是可能发生幻读的。 serializable 隔离级别下什么并发事务的情况都不会发生因为它是一个一个事务的执行的就是排队进行事务执行,性能极差。

在日常工作中我们使用的隔离级别是RC和RR多一些。我们mysql中默认是(repeatable read)这个隔离级别。在mysql中RR和SQL标准中不同,mysql是可以避免幻读发生的。 也就是说再mysql默认的隔离级别下是不会发生 脏读、不可重复读、幻读的情况。就算你插入了数据我的事务也读不到,可以说事务间是相互不干扰的。 Mysql就是依赖MVCC机制来实现事务间不干扰的。

MVCC前置知识,Undo-Log版本链

在正式分析MVCC多版本并发控制机制之前先需要了解Undo-log版本链,简单来说我们每条数据其实有两个隐藏字段。

  1. trx_id 就是开启事务时的事务id
  2. roll_pointer 就是上一次的事务id 举例说明一下假设你现在新增一条数据到表,现在的事务id假设等于50就是 trx_id=50,roll_pointer为空因为原本这条数据不存在,所以没有上一次事务id。

假如现在事务B来修改这条记录把值A改为值B,那么在更新前会生成一个Undolog记录然后并用roll_pointer指向上一个实际的值。 看上图可以知道现在事务B 修改了数据为值B它的roll_pointer 指向了undolog 也就是上一次实际的值。 如果现在事务C又来修改了看下图: 所以到现在应该明白了我们每次事务修改的时候都是用roll_pointer 指针串联起了数据变化的版本链。