MySQL 系列 事务实现篇

讲述事物在innodb上的应用与实现

Posted by lichao modified on October 26, 2023

InnoDB 事务实现

  • 隔离性:写隔离是锁来实现,读隔离是 MVCC 实现;
  • 原子型、持久性:通过Write-Ahead Logging 机制,即 redo log 来实现事务的原子性、持久性;
  • 一致性:通过 undo log 来保证事务的一致性,帮助事务回滚及 MVCC 的功能;
  • redo log 基本上都顺序写的,在数据库运行期间不需要对 redo log 文件进行读取操作。
  • undo log 是需要进行随机读写的。

MySQL中的隔离级别

MySQL 定义了四种隔离级别,包括一些具体规则,用于限定事务内外哪些改变是可见的,哪些改变是不可见的。低级别的隔离一般支持更高的并发处理,并且拥有更低的系统开销。

对于Innodb存储引擎来说,其默认的事务隔离级别是read repeatable,完全遵循和满足事务 ACID 特性。

Innodb的read repeatable隔离级别与上述理论中的 read repeatable 隔离有一定差异。一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。该事务隔离级别限制了不可重复读取、幻读和脏读,即InnoDB在read repeatable事务隔离级别下已经完全保证事务隔离性的要求,即达到SQL标准的serializable隔离级别。

InnoDB使用Next-key Lock锁和MVCC避免了不可重复读和幻读的问题。在Next Key Lock算法下,对于索引的扫描,不仅是锁住扫描到的索引,而且还锁住那些索引覆盖的范围(gap),因此在这个范围内插入都是不被允许的。

1
2
3
  select * from table where col = XXX in share mode;      
    if not found any row:     
       insert into table values(...);      

用户可以通过InnoDB存储引擎的Next Key Lock机制在应用层面实现唯一性检查。 如果用户通过索引查询一个值,并对该行加上一个 SLock, 那么即使查询的值不存在,其锁定的也是一个范围,因此若没有返回任何行,那么新插入的值一定是唯一的。

在实现上,数据库里面会创建一个视图(ReadView),访问的时候以视图的逻辑结果为准。在“可重复读”隔离级别下,这个视图是在事务启动时创建的,整个事务存在期间都用这个视图。在“读已提交”隔离级别下,这个视图是在每个 SQL 语句开始执行的时候创建的。这里需要注意的是,“读未提交”隔离级别下直接返回记录上的最新值,没有视图概念;而“串行化”隔离级别下直接用加锁的方式来避免并行访问。

相关SQL命令

  • 在MySQL数据库中查看当前事务的隔离级别:
1
  select @@tx_isolation; 
  • 在MySQL数据库中设置事务的隔离级别:
1
2
  set  [glogal | session]  transaction isolation level 隔离级别名称; 或:
  set tx_isolation=’隔离级别名称;