编辑
2026-01-19
笔记
00
请注意,本文编写于 54 天前,最后修改于 54 天前,其中某些信息可能已经过时。

目录

可重复读的实现
事务的启动方式
如何查询长事务

03 | 事务隔离

数据库事务的特性是 ACID:

  • Atomicity,原子性
  • Consistency,一致性
  • Isolation,隔离性
  • Durability,持久性

本篇笔记侧重讲 “隔离性”

常见的隔离性问题有:

  • 脏读,dirty read
  • 不可重复读,non-repeatable read
  • 幻读,phantom read

为解决这些问题,就有了 “隔离级别”,SQL 标准的事务隔离级别有:

  • 读未提交,read uncommitted
  • 读提交,read committed
  • 可重复读,repeatable read
  • 串行化,serializable

面试题:MySQL 的默认事务隔离级别是什么?

  • MySQL 默认的事务隔离级别是【可重复读】
  • Oracle 默认的事务隔离级别是【读提交】

可以通过启动参数 transaction-isolation 修改 MySQL 的默认事务隔离级别,还可以通过 show variables 来查看:

sql
mysql> show variables like 'transaction_isolation'; +-----------------------+----------------+ | Variable_name | Value | +-----------------------+----------------+ | transaction_isolation | READ-COMMITTED | +-----------------------+----------------+

可重复读的实现

MySQL 中每条记录在更新的时候都会记录一条回滚操作,通过对记录上最新值叠加回滚操作,就可以得到之前的值。假设一个值从 1 被按顺序改成了 2、3、4,在回滚日志里面就会有类似下面的记录:

image.png

如图所示,不同时间启动的事务会有不同的视图,即同一条记录在系统中可以有多个版本,这就是数据库的多版本并发控制,即 MVCC.

即使现在有另外一个事务正在将 4 改成 5,这个事务跟 read-view A、B、C 对应的事务是不会冲突的。

回滚日志什么时候删除

会在不需要的时候删除

建议不要使用长事务,长事务会在系统中记录很老的事务视图,导致大量占用存储空间。

在 MySQL 5.5 及以前的版本,回滚日志是跟数据字典一起放在 ibdata 文件里的,即使长事务最终提交,回滚段被清理,文件也不会变小。作者见过数据只有 20GB,而回滚段有 200GB 的库。最终只好为了清理回滚段,重建整个库。

事务的启动方式

  1. 显式启动事务语句

    • 启动事务:begin 或 start transaction
    • 提交事务:commit
    • 回滚事务:rollback
  2. 通过 set autocommit=0 关闭自动提交。关闭后,事务还是会自动启动的,支持要手动 coomit 活 rollback。建议使用 set autocommit=1 以通过显示语句的方式(即上面第一种方式)启动事务。

如何查询长事务

可以在 information_schema 库的 innodb_trx 这个表中查询长事务。

查找持续时间超过 60s 的事务

sql
select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started)) > 60

本文作者:菜宝熊

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!