什么是锁?
锁是用于管理不同事务对共享资源的并发访问,保证数据的完整性和一致性。
数据库锁和传统意义的锁(比如 Java 的锁)有哪些区别呢?
lock | latch | |
---|---|---|
对象 | 事务 | 线程 |
保护 | 数据库内容 | 存储数据结构 |
持续时间 | 整个事务过程 | 临界资源 |
模式 | 行锁、表锁、意向锁 | 读写锁、互斥量 |
死锁 | 通过 waits-for graph、time out 等机制进行死锁检测与处理 | 无死锁检测与处理机制。仅通过应用程序加锁的顺序(latch leveling)保证无死锁的情况发生 |
存在于 | Lock Manager 的哈希表中 | 每个数据结构的对象中 |
在数据库中,锁保护的对象是事务,锁持续的时间是整个事务过程,只有在整个事务 commit 之后,锁才会释放,也就是说如果当前事务执行时间很长,锁将会被一直持有。
latch 是针对程序内部的资源( 比如:全局变量)的锁的定义,而这里的 lock 针对的是数据库的事务。
lock 是由 latch 来保证和实现的。
通过如下命令来查看 InnoDB latch 的持有情况:
mysql> show engine innodb mutex; -- 主要给内核开发人员给予帮助
+--------+-----------------------------+-----------+
| Type | Name | Status |
+--------+-----------------------------+-----------+
| InnoDB | rwlock: dict0dict.cc:1184 | waits=2 |
| InnoDB | rwlock: log0log.cc:785 | waits=21 |
| InnoDB | sum rwlock: buf0buf.cc:1379 | waits=138 |
+--------+-----------------------------+-----------+
3 rows in set (0.01 sec)
一般我们也不关注 InnoDB latch 的持有情况,内核开发人员才会关心,这些信息可以帮助他们优化 InnoDB 的内核代码。
执行什么操作会导致 InnoDB 加锁?
在这之前先简单了解一下什么是快照读和当前读?
快照读(snapshot read):普通的 select … 操作都是快照读,读取的数据可能是历史快照数据,不是数据库最新的数据,快照读是通过 MVCC 和 Undo Log 实现的。
当前读(current read):读取的是数据库中最新版本的数据,如下操作都是当前读:
- select … lock in share mode
- select … for update
- insert …
- update …
- delete …
快照读是不需要执行加锁操作的,只有当前读才会导致 InnoDB 加锁。
作者:殷建卫 链接:https://www.yuque.com/yinjianwei/vyrvkf/zdfy3q 来源:殷建卫 - 架构笔记 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。