MYSQL复习——第七章:事务

7.1 事务特性:ACID

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

7.2 事务实现

  • redo
  • undo
  • purge
  • group commit

开启事务方法

BEGIN; START TRANSACTION; SET AUTOCOMMIT=0

脏读,幻读,不可重复读

  • 脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。
  • 不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,重点在updata和delete
  • 幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,重点在insert

隔离级别

1.读未提交

写加锁(直到事务结束释放),读不加锁。

排他锁会阻止其它事务再对其锁定的数据加读或写的锁,但是对不加锁的读不起作用。

2.读已提交

读不加锁,写加锁。

采用Record Lock加锁

读操作用MVCC保证,读一条语句看到的是一个snapshoot version,解决了脏读问题(只看到更新前的版本)。但是基于语句级别的ReadView,会导致不可重复读,同一个事务先后两次不一致。

写操作解决脏读

读自己的时候是当前读

3.可重复读

读不加锁,写加锁,但会有Write Skew异常。

采用Next-key Lock加锁

读操作用MVCC保证,基于事务级别的ReadView

对于写操作加写锁:

(1)有索引:对于索引上有唯一约束且为等值条件的情形,只锁定索引记录(行锁)。对于其它情形,加间隙锁。

(2)没有索引:表锁(或者说给所有行加锁?)

但是在标准的事务隔离级别定义下,REPEATABLE READ是不能防止幻读产生的(比如Oracle的RR级别会存在幻读)。

Innodb利用Gap Locks和Next-Key解决了幻读问题。但是需要 加上 select for update/lock in share mode 变成当前读避免幻读,普通读select存在幻读

4.串行化

所有普通 select 都转化成 select ... lock in share mode 加共享锁

两阶段锁协议:

加锁阶段:在该阶段可以进行加锁操作。在对任何数据进行读操作之前要申请并获得S锁(共享锁,其它事务可以继续加共享锁,但不能加排它锁),在进行写操作之前要申请并获得X锁(排它锁,其它事务不能再获得任何锁)。加锁不成功,则事务进入等待状态,直到加锁成功才继续执行。

解锁阶段:当事务释放了一个*以后,事务进入解锁阶段,在该阶段只能进行解锁操作不能再进行加锁操作。

MVCC多版本并发控制和ReadView

(1)每条记录都会保存两个隐藏列:trx_id(事务id)和roll_pointer(回滚指针)

(2)每次操作都会生成一条undo log日志,回滚指针指向前一条记录

ReadView: [未提交的事务id的数组] + 最大事务id,并根据版本链向下找

eg. [100,300] ,300

如果找到50,可读,50 < 100

如果找到200,可读,200<300且不在数组中

如果找到300或者100,不可读,因为在数组中

MYSQL复习——第七章:事务

MYSQL复习——第七章:事务

概念

1.快照读和当前读

快照读:读取的是快照版本,也就是历史版本

当前读:读取的是最新版本

普通的SELECT就是快照读,而UPDATE、DELETE、INSERT、SELECT ...  LOCK IN SHARE MODE、SELECT ... FOR UPDATE是当前读。

2.一致性非锁定读和一致性锁定读

(1)一致性锁定读

在默认级别下,SELECT操作都使用一致性非锁定读,即读快照版本不加锁。但是有两种情况例外。

SELECT ... LOCK IN SHARE MODE

给记录假设共享S锁,这样一来的话,其它事务只能读不能修改,直到当前事务提交

SELECT ... FOR UPDATE

给索引记录加X锁,这种情况下跟UPDATE的加锁情况是一样的

(2)一致性非锁定读

consistent read (一致性读),InnoDB用多版本来提供查询数据库在某个时间点的快照。如果隔离级别是REPEATABLE READ,那么在同一个事务中的所有一致性读都读的是事务中第一个这样的读读到的快照;如果是READ COMMITTED,那么一个事务中的每一个一致性读都会读到它自己刷新的最新一份快照版本。Consistent read(一致性读)是READ COMMITTED和REPEATABLE READ隔离级别下普通SELECT语句默认的模式。一致性读不会给它所访问的表加任何形式的锁,因此其它事务可以同时并发的修改它们。

Reference

https://www.jianshu.com/p/dab1c0ecbac0