15事务隔离

  • 读未提交
    允许读到未提交数据,查询不使用锁,可能会产生脏读、不可重复读、幻读等情况。

  • 读已提交
    就是只能读到已经提交的内容,可以避免脏读的产生,属于RDBMS中常见的默认隔离级别(比如说 Oracle和SQL Server),但如果想要避免不可重复读或者幻读,就需要我们在SQL查询的时候编写带加锁的SQL语句(我会在进阶篇里讲加锁)。

  • 可重复读(MySQL默认)
    保证一个事务在相同查询条件下两次查询得到的数据结果是一致的,可以避免不可重复读和脏读,但无法避免幻读。

  • 可串行化
    将事务进行串行化,也就是在一个队列中按照顺序执行,可串行化是最高级别的隔离等级,可以解决事务读取中所有可能出现的异常情况,但是它牺牲了系统的并发性。

三个隐藏列:
DB_TRX_ID 事务ID,最后一个对该数据进行插入或更新的事务ID
DB_ROLL_PTR:旧数据指针,指向undolog;
ROW_ID没有主键列时

undolog:记录事务id、对应的操作、当前值

读已提交不是行锁实现的,是MVCC通过undolog实现的,每次查询数据创建ReadView(相同查询也创建新的),通过undolog查询到已提交的数据
ReadView包含三个字段creator_trx_id当前事务,min_trx_id未提交事务, max_trx_id未开始事务,trx_ids当前活跃的事务列表

可见性规则:

  • undolog_trx_id < min_trx_id 可见
  • undolog_trx_id > max_trx_id 不可见
  • min_trx_id < undolog_trx_id < max_trx_id
    • 若undolog_trx_id是creator_trx_id,可见
    • 若undolog_trx_id在活跃事务数组中,表示事务未提交,不可见
    • 若undolog_trx_id不在活跃事务数组中,表示事务已提交,可见

重复读,MVCC控制,相同查询只创建一次ReadView

串行化:表锁

MVCC

通过undolog+readview实现
有隐藏数据行指向undolog,每次启动事务读创建readview指向对应的undolog节点

解决问题

  • 读写阻塞
    通过MVCC可以让读写互相不阻塞,即读不阻塞写,写不阻塞读,这样就可以提升事务并发处理能力。
  • 降低死锁概率
    MVCC采用了乐观锁的方式,读取数据时并不需要加锁,对于写操作,也只锁定必要的行。
  • 解决一致性读的问题
    一致性读也被称为快照读,当我们查询数据库在某个时间点的快照时,只能看到这个时间点之前事务提交更新的结果,而不能看到这个时间点之后事务提交的更新结果。

快照读、当前读

快照读:不加锁的简单select都属于快照读
如:select * from player where

当前读:读取最新数据,非历史版本数据。加锁select或数据增删改查进行当前读
如:select * from player LOCK IN SHARE MODE (共享锁)
select * from palyer FOR UPDATE (排他锁)
insert into player values … (排他锁)
delete from player where … (排他锁)
update player set … (排他锁)