什么是锁?

    锁是用于管理不同事务对共享资源的并发访问,保证数据的完整性和一致性。

    数据库锁和传统意义的锁(比如 Java 的锁)有哪些区别呢?

    lock latch
    对象 事务 线程
    保护 数据库内容 存储数据结构
    持续时间 整个事务过程 临界资源
    模式 行锁、表锁、意向锁 读写锁、互斥量
    死锁 通过 waits-for graph、time out 等机制进行死锁检测与处理 无死锁检测与处理机制。仅通过应用程序加锁的顺序(latch leveling)保证无死锁的情况发生
    存在于 Lock Manager 的哈希表中 每个数据结构的对象中

    在数据库中,锁保护的对象是事务,锁持续的时间是整个事务过程,只有在整个事务 commit 之后,锁才会释放,也就是说如果当前事务执行时间很长,锁将会被一直持有。

    latch 是针对程序内部的资源( 比如:全局变量)的锁的定义,而这里的 lock 针对的是数据库的事务。

    lock 是由 latch 来保证和实现的。

    通过如下命令来查看 InnoDB latch 的持有情况:

    1. mysql> show engine innodb mutex; -- 主要给内核开发人员给予帮助
    2. +--------+-----------------------------+-----------+
    3. | Type | Name | Status |
    4. +--------+-----------------------------+-----------+
    5. | InnoDB | rwlock: dict0dict.cc:1184 | waits=2 |
    6. | InnoDB | rwlock: log0log.cc:785 | waits=21 |
    7. | InnoDB | sum rwlock: buf0buf.cc:1379 | waits=138 |
    8. +--------+-----------------------------+-----------+
    9. 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 来源:殷建卫 - 架构笔记 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。