并发,重头戏
Locking
Shared and Exclusive Locks
InnoDB默认使用的是行级锁(row-level locking),具体分成两种,shared(s) locks和exclusive(x) locks。前者用于读,后者用于更改与删除。
- T1 s lock->T2 s lock get immediately
- T1 s lock->T2 x lock hold on
- T2 x lock->T2 any lock hold on
Intention Locks
意向锁(intention locks)是一种表锁,用于告诉其他用户该事务在之后的操作中会对行进行什么类型的锁。
- Intention shared lock(IS):意向共享锁
- Intention exclusive lock(IX):意向排他锁
使用方法
- 事务在申请行级共享锁之前,需要申请IS锁
- 事务在申请行级排他锁之前,需要申请IX锁
冲突关系
下表为普通的表锁与意向锁之间的冲突关系,一旦出现冲突,只有当前的锁被释放才能够进行进一步的操作。此外,意向锁只会和表锁产生冲突,行锁粒度的冲突交由行锁去处理,所以IS和IX可以共存。
x | IX | S | IS | |
---|---|---|---|---|
X | × | × | × | × |
IX | × | √ | × | √ |
S | × | × | √ | √ |
IS | × | √ | √ | √ |
Record Locks
用于锁定索引本身的锁,不论是主索引还是辅助索引。例如
1 | SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE; |
Gap Locks
Record Locks的进阶版,选中一个范围内的数据,不允许其他事务在这个范围内进行增删改查。Gap Locks可用于单索引,多索引,甚至没有索引也是可以的。
1 | SELECT c1 FROM t WHERE c1 BETWEEN 10 AND 20 FOR UPDATE; |
对于读unique列的操作,加上Gap Locks是多此一举的行为。多个Gap Locks是可以被Merge的,在真正的修改操作进行前,并不会导致任何冲突。
Next-Key Locks
Next-Key Locks是Record Locks和Gap Locks的复合体。该操作并不需要手动指定锁的范围,而是锁住相关行的前/后一行之间的间隙。
Insert Intention Locks
Gap锁的一种,用于表示该事务会在一定范围内插入数据,以提高并行插入的能力,如果两个事务的Insert Intention Locks没有重叠区域,则把他们一起运行也不会对系统有什么不良影响。
AUTO-INC Locks
特殊的表锁,用于自增主键
Predicate Locks for Spatial Indexs
空间索引(地理数据之类的二维索引)不在考虑范围内,所以忽略
Transaction
Transaction Isolation
Read Uncommited
完全不加锁,一切随缘,脏读幻读都有可能
Read Committed
单次读的一致性有保障,但一个事务中的所有读的一致性没有保障,有可能出现幻读
- 读一般只会上行锁,只有在外键和重复键检查的时候才会用Gap Locks
- 对于删除和修改,依然使用行锁,在Where筛选结束后,将会释放那些无关的行,虽然概率小,但还是会死锁
- 要修改已经被锁上的行时,MySQL会先读一下,初步确定是否符合Where条件,符合条件后又再次进行上锁与读取的操作
Repeatable Read(default)
一个事务的读一致性有所保障
- Unique Index,只会锁一行
- 其他的,上Gap Locks/Next-Key Locks
Serializable
最高强度的隔离,会在每一句SELECT之后加上’FOR SHARE’
AutoCommit, Commit&Rollback
AutoCommit
每个SQL语句都会构成一个事务,没有错误的事务被执行后都会被Commit,错误的执行会被Rollback
Commit
意味着该事务的操作会被其他事务看到
Consistent Nonlocking Reads
使用MVCC+s locks让多个事务同时读写数据,而且不会互相干扰,具体效果依据隔离程度决定。在以下情况,该功能不可用
- DROP TABLE
- ALTER TABLE
Locking Reads
普通的SELECT可能隔离强度不足,手动加锁
- SELECT FOR SHARE
- SELECT FOR UPDATE
Deadlocks
原因
死锁是由写操作产生的,所以改变隔离状态不会让死锁问题得到改善。
- 写粒度要小
- 多用事务,少用表锁
Detection and Rollback
- 碰撞检测(有向图找环);如果出现超过200个事务在等待;也可以关掉使用事务超时进行判断
- 选择插入/更新/删除行数最小的事务回滚
- InnoDB回滚时,会释放所有的锁。但是,存在个别情况,例如语句执行失败后,仅仅回滚这一条语句,则不会释放该语句的锁,因为InnoDB不存储SQL语句与锁的对应关系
- 如果是SELECT在事务中调用预先设置好的内建函数,而且出现语句失败,则该语句会回滚,如果又进一步手动执行ROLLBACK,会导致整个事务一起回滚
Scheduling
Contention-Aware Transaction Scheduling(CATS),基于权重决定事务优先关系,权重由以下内容决定
- 为阻塞事务数目多的事务更高的权重
- 阻塞数目一样多,等待时间长的更高权重