首页 事务隔离:为什么你改了我还看不见?
文章
取消

事务隔离:为什么你改了我还看不见?

事务隔离级别

  1. 读未提交(read uncommitted),事务未提交,它做的变更就可被其他事务看见
  2. 读已提交(read committed),事务提交后,它做的变更才可见
  3. 可重复读(repeatable read),事务在执行过程中看到的数据,与事务开启时看到的数据是一致的
  4. 串行化(serializable),顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。

事务隔离级别的实现机理

事务上的视图

事实上,当一个事务访问一条记录时,数据库服务器会为这个这条记录生成一个视图,而事务访问时都会以这个视图的逻辑结果为准;

  1. 读未提交没有视图的概念,它总是读取一条记录的最新值
  2. 读已提交,视图是在每个SQL执行的时候生成的,因此如果是同一条SQL,每次执行的视图可能会不一样(也就是如果当前记录被已提交事务修改)
  3. 可重复读,视图是在事务开启的时候生成的,因而事务的整个存在期间(未提交前)都是以这个视图为准的
  4. 串行化,直接用加锁的方式避免事务的并行访问

如何查看当前事务的隔离级别

1
show variables like 'transaction_isolation';

事务的多版本并发控制

从日志系统那一章我们知道:在 InnoDB 中每次进行更新操作时都会在 redo log 中进行记录,而事务中的最新值可以通过 redo log 回滚到前几个状态的值。事实上事务的原子性就是通过 redo log 实现。

假设在当前的事务中,一条数据经过了如下变化:

一条记录的回滚日志

其中 read-view 代表视图,而对于不同时刻启动的事务,会分别用不同的视图,使得同一条数据在不同的事务居然会有呈现不同的值,比如上图一共有 A、B、C 三个视图,数据的值分别是 1、2、4。这就是数据库的多版本并发控制(MVCC)。

事务的启动方式

手动操作事务:

1
2
3
4
5
6
7
8
9
10
11
12
-- 关闭事务的自动提交
set autocommit=0 
-- 开启事务(或者 start transaction)
begin 
-- 提交事务
commit
-- 回滚事务
rollback
-- 提交事务并自动开启下一个事务
commit work and chain
-- 查找持续时间超过60s的事务
select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>60;
本文由作者按照 CC BY 4.0 进行授权

字典项自动翻译器

基础架构:一条SQL查询语句是如何执行的