锁是一种很珍贵的资源。锁一定是并发场景下才会出现的。
保证数据的隔离性,一致性。
1.latch
这个锁存在于内存中,用来控制并发访问的,保护的是内存数据结构。他锁住的是并发资源。就是临界区。
就是java和golang中的mutex。
他加锁的对象是线程。持续时间是临界时间。只有读写锁和互斥量。并且没有死锁检测机制,这个是纯粹靠应用程序加锁的顺序保证无死锁。
查看:show engine innodb mutex;
2.lock
加锁的对象是事务。
持续的时间是整个事务周期。死锁通过waits-for graph , time out机制控制
存在于lock manager的hashtable中。
分类:
S行级共享锁(lock in share mode)
X行级排它锁(写和当前读)
IS
IX
AI自增锁
相关的信息你可以show engine innodb status\G,找到transaction部分。
innodb_lock_wait_timeout可以调少一点,调到秒级。
s和x就不说了,老生常谈了。主要聊一下下面的三种。
对于is和ix。表示下一层级请求的锁的类型。
is表示事务想获得一个表中某几行的共享锁。
ix表示事务想获得一个表中某几行的排它锁。
意向锁都是表锁。意向锁都是为了实现多粒度级别的锁。
举一个例子。
数据库的层级应该是怎么划分的?
database table page row
4个层级。
我要对row=1这行加一个x锁。那么从上至下,锁是怎么加的?
database(IX) table(IX) page(IX) row(X)
这时候,我又要对row=2这行加一个X锁。那么database层能不能拿到IX锁?
答案是能,因为IX表示的是下一层级的锁,也就是IX是table的锁,database本身没有锁。而到了table层级,他持有的也是IX锁,表示我table层级没有锁,我持有的是下一层page的锁。到了page层同理。只有到了row级,发现,如果我们两个需要对同一行进行dml,才会发生争用。
而对于mysql来说,上面的四个层级,意向锁只会在table层发生。database和page是没有的。所以说意向锁是表锁。
有个参数innodb_status_output_locks这个参数打开,你看锁信息会多一点。
还有几张系统表:
sys.innodb_lock_waits
ps.innodb_trx
ps.innodb_locks
ps.innodb_lock_waits
show engine innodb status中的heap no表示的是page中的插入顺序。也表示的是具体的记录,也是行锁的表现。每页的heap no都是从2开始的。0和1被系统给了min和max。
innodb中的锁管理:
每个页会有个锁的对象
也就是说,锁其实是要消耗资源的。
通过位图的方式来管理锁的。一个锁可能是在30字节左右。