一.背景
了解锁机制能让我们开发更加高效的程序,最小化锁带来的性能开销。
二.锁概念
锁是存储引擎为了实现共享资源并发访问的一种管理机制来保证数据的一致性和完整性。
先整体看下锁的使用情况
show status like 'innodb_row_lock%';
current_waits:代表正在等待的线程的数量。(注意是线程的数量,也就是事务数,不是加锁的数量)
lock_waits:代表历史上等待线程的数量。(同一个线程尝试多次会记录多次)
其他几个值根据字面意思就能看出来。
三.innodb中锁的类型
共享锁:对一行数据加的只读锁。(意味着此条记录只允许被读,不许被修改)
排它锁:对一行数据加的排它锁。(意味着此条记录不许其他线程加任何锁)
注意:共享锁(S)和排它锁(X)只可以对一行记录加锁。
就是因为S和X锁都只针对记录,而对于一些操作如alter table仅仅想知道这种表现在有没有数据被修改ing,所以为了处理这类操作引入了意向锁(Intention Lock)。
要为一行记录加S或X锁,依次要给库、表、页加对应的IS或IX锁,最后才对行加S或X锁。
四.直观感受锁
我们先来看下实践,后面再详细的分析理论。
下面分别查看当前锁使用情况。
select * from information_schema.innodb_trx;--当前未提交事务的状态
select * from information_schema.innodb_locks;--当前正在争夺的锁
select * from information_schema.innodb_lock_waits;--当前等待的锁
1>.场景一:模拟单个事务未提交
1.使用root用户登录
select * from information_schema.innodb_trx;--当前未提交事务的状态
这张表主要记录了当前事务的状态,开始时间,权重(反映锁住的行数,死锁回滚权重小的),线程id。
这时候,其他两张表因为没有竞争所以没有数据。
结论:正在进行的事务,可以通过表1去查看开始的时间,权重等信息。
2>.场景二:事务1加X锁未提交,事务2修改同一行的数据。
图三因为超时回滚了,重新提交的,所以事务id+1了。应该是10872。
表2:可以看出存在竞争的锁的情况。
表3:可以看出阻塞的和等待的事物id。
结论:通过这3张表,我们可以分析出,当前锁的基本情况。
五.行锁的3种算法概念
innodb锁的三种算法:
1.record lock 加在索引上
2.Gap lock ReadRepeated隔离级别加在索引的范围上,但不包含本身
3.next-key lock 锁定范围和记录本身,在读取已删除的数据需要加这个锁,RR下默认使用这种锁,这种锁其实就是上面两种锁的组合,对记录加next-key为(],对右边加gap锁。
在使用唯一索引时降级为record lock而不是next