From c629b0ba505f57ffb79302fa4278392155853dca Mon Sep 17 00:00:00 2001 From: asahi Date: Mon, 11 Nov 2024 00:12:45 +0800 Subject: [PATCH] =?UTF-8?q?=E9=98=85=E8=AF=BBmysql=E6=84=8F=E5=90=91?= =?UTF-8?q?=E9=94=81=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mysql/mysql文档/锁.md | 68 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 mysql/mysql文档/锁.md diff --git a/mysql/mysql文档/锁.md b/mysql/mysql文档/锁.md new file mode 100644 index 0000000..e049f2f --- /dev/null +++ b/mysql/mysql文档/锁.md @@ -0,0 +1,68 @@ +# 锁 +## lock 和 latch +在mysql数据库中,lock和latch都可以被称之为锁,但是两者锁包含意义不同。 +### latch +latch一般为轻量级的锁,要求锁定时间通常非常短,否则会影响性能。在innodb中,latch可以分为mutex和rwlock。 + +`latch通常被用于防止代码中临界资源的并发访问`,保证并发操作的安全性。latch操作通常没有死锁检测机制。 + +### lock +lock和latch则稍有区别,lock一般针对的是事务,用于锁定数据库中的表、页、行等数据。并且,`lock一般在数据库事务进行commit或rollback后才释放`。 + +在innodb中,lock拥有死锁检测机制。 + +latch和lock的比较如下: +| | lock | latch | +| :-: | :-: | :-: | +| 对象 | 事务 | 线程 | +| 保护 | 数据库内容 | 代码中的临界资源 | +| 持续时间 | 整个事务过程 | 临界资源 | +| 模式 | 行锁、表锁、意向锁 | 读写锁、互斥量 | +| 死锁 | 通过waits-for graph、timeout等机制检测死锁 | 无死锁检测机制 | + +在innodb中,可以通过`show engine innodb status`以及`information_schema`下的`innodb_trx`来查看锁的情况。 + +## innodb中的锁 +innodb中针对行级锁有如下两种实现: +- S lock(共享锁):允许事务针对一行数据进行读取 +- X lock(排他锁):允许事务针对一行数据进行更新和删除 + +S lock和S lock之间可以互相兼容,但是S lock和X lock、 X lock和 X lock之间都是不兼容的。当一个事务t持有某行数据的X lock时,其他事务必须等待事务t提交或回滚之后才能获取该行数据的S lock或X lock。 + +除了行锁之外,innodb还支持多粒度的锁定,允许行级和表级的锁同时存在。为了支持该操作,innodb引入了一种额外的加锁方式`意向锁`。 + +### 意向锁 +意向锁支持多粒度加锁,允许行锁和表锁共存。例如,`lock tables ... write`会在指定表上加X锁。为了在多个粒度上进行加锁,innodb使用了意向锁,意向锁是表级锁,代表事务稍后需要为表中的数据加上哪种锁。 + +意向锁分为两种类型: +- IS: 事务旨在为table中独立的行添加共享锁 +- IX: 事务旨在为table中的行添加排他锁 + +例如,`select ... for share`设置IS锁,而`select ... for update`则设置了IX锁。 + +意向锁协议如下: +- 在事务获取table中某行记录的s锁之前,其必须获取table的IS或更高级别锁 +- 在事务获取table中某行记录的x锁之前,其必须获取table的IX锁 + +table level锁的兼容性如下所示: +| | x | ix | s | is | +| :-: | :-: | :-: | :-: | :-: | +| x | 不兼容 | 不兼容 | 不兼容 | 不兼容 | +| ix | 不兼容 | 兼容 | 不兼容 | 兼容 | +| s | 不兼容 | 不兼容 | 兼容 | 兼容 | +| is | 不兼容 | 兼容 | 兼容 | 兼容 | + +如果要加的锁和已经存在的锁兼容,那么它将被授予请求加锁的事务;要加的锁和已经存在的锁冲突时,则不会授予。请求加锁的事务将会阻塞,一直等待到存在冲突的锁被释放。 + +如果事务中的锁请求因为与现有锁冲突而无法被授予,并且造成死锁,那么会抛出异常。 + +> 意向锁和意向锁之间是兼容的,故而意向锁只会和全表扫描相冲突。 + +引入意向锁的意图是展示有人锁定了表中的某一行,或是将要锁定表中的某一行。 + +事务和意向锁相关的信息可以通过`show engine innodb status`来展示,其输出如下: +``` +TABLE LOCK table `test`.`t` trx id 10080 lock mode IX +``` + +