From d2f82e210c573c718961c0e26f06ac078ecc3564 Mon Sep 17 00:00:00 2001 From: asahi Date: Wed, 13 Nov 2024 00:13:27 +0800 Subject: [PATCH] =?UTF-8?q?=E9=98=85=E8=AF=BBmysql=E4=B8=80=E8=87=B4?= =?UTF-8?q?=E6=80=A7=E8=AF=BB=E7=9A=84=E7=9B=B8=E5=85=B3=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mysql/mysql文档/锁.md | 43 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/mysql/mysql文档/锁.md b/mysql/mysql文档/锁.md index 33d398b..fe85a81 100644 --- a/mysql/mysql文档/锁.md +++ b/mysql/mysql文档/锁.md @@ -80,4 +80,47 @@ Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 2: len 7; hex b60000019d0110; asc ;; ``` +### 一致性读 +#### 一致性非锁定读 +`一致性非锁定读`是指innodb通过mvcc(多版本并发控制)来读取行数据。如果当前待读取的行正在执行update或delete操作,那么此时`读取行的操作并不会被阻塞,而是会去读取当前被修改行的快照历史版本`。这种行为被成为`非锁定读`。 + +在非锁定读的场景下,事务读取行数据时并不需要等待其他事务持有的X锁释放,而是之前读取行数据的历史快照版本。`历史快照版本通过`undo log`来生成`。 + +非锁定读极大的提高了数据库的并发性,一个事务对行数据的写操作并不会阻塞其他的事务对该行进行读取。innodb在默认的隔离级别下,默认通过非锁定读来读取数据。 + +`在不同事务隔离级别下,读取数据的方式可能会不同,并非所有隔离级别都采用非锁定读的读取方式`。 + +> #### 多版本并发控制(mvcc) +> 在非锁定读场景下,一行数据通常不会只有一个历史版本,其数据快照并不只有一个,这被称为多版本并发控制。 +> +> innodb对read committed和repeatable read隔离级别使用非锁定读,但是,两种隔离级别`快照定义并不相同`。 +> +> #### read committed +> +> 在read committed隔离级别下,非锁定读总是会读取行数据`最新的快照`。 +> +> #### repeatable read +> 在repeatable read隔离级别下,非锁定读则是会读取`事务开始时的行数据版本`。 + + + + +#### 一致性锁定读 +在默认隔离级别下,read committed和repeatable read都是用非锁定读,但是,可以通过语法显式的支持锁定读。`用户可以通过加锁来保证读取数据的一致性`。 + +在通过select语句对数据加锁时,支持加两种类型的锁: +- select ... for update +- select ... lock in share mode + +`select ... for update`实际是对读取的行记录加上X锁,其他事务均不能对该数据添加任何的锁。 + +`select ... lock in share mode`则是对读取的记录加上S锁,其他事务可以向被锁定记录加S锁,但是不能加X锁。 + +`对于非锁定读,即使数据被添加了X锁,也可以进行读取。`只有通过`for update`或`lock in share mode`在读取时添加X锁或S锁时,读取操作才会被阻塞。 + +并且,`for update`或`lock in share mode`添加的行锁,在事务commit或rollback时会被释放。 + + + +