事务与隔离级别

事务四要素:ACID
原子性(Atomicity)
一致性(Consistency)同一个事务读取数据的一致性
隔离性(Isolation)事务设立了不同程度的隔离级别,通过适度的破坏一致性,得以提高性能;
持久性(Durability)

隔离级别
读未提交(Read Uncommitted)
读已提交(Read Committed): 事务中只能看到已提交的,不会出现脏读(脏读是没有提交的事务被其他事务读取到了)现象,高并发采用改隔离级别;
通过对写操作加持续X锁、对读操作加临时S锁实现
可重复读(Repeatable Read): 解决了不可重复读(不可重复读是读取了另一个事务提交之后的修改)问题,但是任然存在幻读问题;
通过对写操作加持续X锁、对读操作加持续S锁实现
序列化(Serializable): 无幻读(幻读是两次读取同一个范围内的记录数不同或者存在先删后增的);使用表级锁

SELECT 快照读
SELECT ... LOCK IN SHARE MODE:当前读加S锁
SELECT ... FOR UPDATE/ INSERT / UPDATE / DELETE:加 X 锁




表锁由 MySQL 服务器实现,行锁由存储引擎实现

InnoDb 的主键索引又被称为聚簇索引,二级索引被称为非聚簇索引,加锁先找到二级索引加锁,再锁聚簇索引

锁冲突,S和S锁兼容,S(共享读锁)和X(独占锁)锁冲突;

记录锁(LOCK_REC_NOT_GAP)
日志关键字 lock_mode X locks rec but not gap
间隙锁(LOCK_GAP)
日志关键字 lock_mode X locks gap before rec
Next-key 锁(LOCK_ORNIDARY)
日志关键字 lock_mode X
说明 是记录锁和间隙锁的组合,它指的是加在某条记录以及这条记录前面间隙上的锁
插入意向锁(LOCK_INSERT_INTENTION)
日志关键字 lock_mode X locks gap before rec insert intention

RC级别也会存在间隙锁、Next-key 锁


排查锁
1 开启监控
SET GLOBAL innodb_status_output=ON;
SET GLOBAL innodb_status_output_locks=ON;
SET GLOBAL innodb_print_all_deadlocks=ON;
2 触发锁
2.1 mysql开启事务 begin
2.2 执行导致锁冲突的sql
3 查找监控日志
SHOW ENGINE INNODB STATUS,看看关键字是哪种锁


常见deadlock问题
1 update
原因:在没有索引的时候,只能走聚簇索引,对表中的记录进行全表扫描。在 RC 隔离级别下会给所有记录加行锁;
解法:where条件加普通索引

2 insert on duplicate key update
原因:出现在insert时候,检测到唯一键冲突的时候,会在冲突所在唯一索引出和之前的间隙处加Next-key lock.
解法:重试(mysql在检测到发生死锁的时候,会随机回滚其中的一个事务,从而解开死锁);
改sql,先查后更新or插入