在MySQL中,事务隔离级别RC(read commit)和RR(repeatable read)两种事务隔离级别基于多版本并发控制MVCC(multi-version concurrency control)来实现。
由于RC隔离级别需要保持语句级别的一致行,事务中每一次读取都是访问当前时间点的已提交数据,因此事务中多条查询语句会创建多个不同的ReadView,开销较大,复杂度更高,而对于RR隔离级别,仅需要一个版本的ReadView,消耗更少,因此Mysql默认使用RR隔离级别。 RC隔离级别获得的是语句级读一致性 RR隔离级别获得的是事务级读一致性 对于RC隔离级别,访问的数据是每次语句执行时间点的数据,而对于RR隔离级别,访问的数据是事务中第一条语句执行时间点的数据。 If the transaction isolation level is REPEATABLE READ (the default level), all consistent reads within the same transaction read the snapshot established by the first such read in that transaction. With READ COMMITTED isolation level, each consistent read within a transaction sets and reads its own fresh snapshot. 在RR隔离级别下,执行start transaction命令后,并未开启事务,而是等到第一条语句执行时开启事务并建立一致性读的snapshot,如果希望在start transaction时就建立一致行读的snapshot,可以使用START TRANSACTION WITH consistent snapshot。
对于RC隔离级别,不需要解决幻读的问题,"当前读"操作只对扫描到的数据进行加锁(行锁),无须使用GAP锁。 对于RR隔离级别,需要防止幻读的问题,"当前读"操作除对烧苗到的数据进行加锁外,还需要使用GAP锁来防止数据插入到新记录。
mysqldump --single-transaction便是基于RR隔离级别来获取一致性数据。 虽然RR隔离级别保证了数据一致性,但是mysqldump并不会在开始时便获取所有表的MDL锁,假设在mysqldump执行期间执行对表TB1的ALTER或DROP操作: 情况1:执行mysqldump的线程先访问表TB1,然后另外线程执行ALTER或DROP操作,则执行mysqldump的线程获取到MDL锁,阻塞执行ALTER或DROP操作的线程。 情况2:线程先执行ALTER或DROP操作,然后mysqldump线程访问修改的表TB1,由于执行ALTER或DROP操作的线程已经修改了TB1的结构,导致执行mysqldump的线程无法获得一致性数据,最终mysqldump失败。