inno db 隔离级别和锁定

发布于 2025-01-07 07:33:57 字数 1330 浏览 1 评论 0原文

我正在阅读一本关于 innodb 事务的手册,但仍然有很多不清楚的东西。例如,我不太理解以下行为:

-- client 1                             -- client 2
mysql> create table simple (col int) 
       engine=innodb; 

mysql> insert into simple values(1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into simple values(2);
Query OK, 1 row affected (0.00 sec)

mysql> select @@tx_isolation;                                                              
+-----------------+                                                                         
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |                                                                         
+-----------------+

mysql> begin;                                    
Query OK, 0 rows affected (0.01 sec)            
                                        mysql> begin;
                                        Query OK, 0 rows affected (0.00 sec)

mysql> update simple set col=10 where col=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

                                         mysql> update simple set col=42 where col=2;
                                         -- blocks

现在,最后一个更新命令(在客户端 2 中)等待。我希望该命令能够执行,因为我假设只有第 1 行被锁定。即使客户端 2 中的第二个命令是 insert,行为也是相同的。谁能描述一下这个例子背后的锁定背景(锁的位置和原因)?

I am reading a manual about innodb transactions but still, there is lots of unclear stuff to me. For instance, I don't quite understand to the following behaviour:

-- client 1                             -- client 2
mysql> create table simple (col int) 
       engine=innodb; 

mysql> insert into simple values(1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into simple values(2);
Query OK, 1 row affected (0.00 sec)

mysql> select @@tx_isolation;                                                              
+-----------------+                                                                         
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |                                                                         
+-----------------+

mysql> begin;                                    
Query OK, 0 rows affected (0.01 sec)            
                                        mysql> begin;
                                        Query OK, 0 rows affected (0.00 sec)

mysql> update simple set col=10 where col=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

                                         mysql> update simple set col=42 where col=2;
                                         -- blocks

Now, the last update command (in the client 2) waits. I would expect the command to execute because I would suppose only the row 1 is locked. The behaviour is the same even if the second command in the client 2 is insert. Could anyone describe the locking background behind this example (where and why the locks)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

乱了心跳 2025-01-14 07:33:57

InnoDB 设置特定类型的锁如下。

  • SELECT ... FROM 是一致读,读取数据库的快照并且不设置锁,除非事务隔离级别设置为 SERIALIZABLE。对于 SERIALIZABLE 级别,搜索在遇到的索引记录上设置共享的下一个键锁。

  • SELECT ... FROM ... LOCK IN SHARE MODE 对搜索遇到的所有索引记录设置共享下一个键锁。

  • 对于搜索遇到的索引记录,SELECT ... FROM ... FOR UPDATE 会阻止其他会话执行 SELECT ... FROM ... LOCK IN SHARE MODE 或在某些事务隔离级别中进行读取。一致读取将忽略读取视图中存在的记录上设置的任何锁定。

  • UPDATE ... WHERE ... 在搜索遇到的每个记录上设置独占的下一键锁定。

  • DELETE FROM ... WHERE ... 在搜索遇到的每个记录上设置独占的下一键锁定。

  • INSERT 在插入的行上设置排他锁。该锁是索引记录锁,而不是下一个键锁(即没有间隙锁),并且不会阻止其他会话插入到插入行之前的间隙中。

InnoDB 有几种类型的记录级锁:

  • 记录锁:这是对索引记录的锁。

  • 间隙锁:这是对索引记录之间的间隙的锁定,或者是对第一个索引记录之前或最后一个索引记录之后的间隙的锁定。

  • 下一个键锁:这是索引记录上的记录锁和索引记录之前间隙上的间隙锁的组合。

查看更多:

使用下一键锁定避免幻象问题

避免死锁

InnoDB sets specific types of locks as follows.

  • SELECT ... FROM is a consistent read, reading a snapshot of the database and setting no locks unless the transaction isolation level is set to SERIALIZABLE. For SERIALIZABLE level, the search sets shared next-key locks on the index records it encounters.

  • SELECT ... FROM ... LOCK IN SHARE MODE sets shared next-key locks on all index records the search encounters.

  • For index records the search encounters, SELECT ... FROM ... FOR UPDATE blocks other sessions from doing SELECT ... FROM ... LOCK IN SHARE MODE or from reading in certain transaction isolation levels. Consistent reads will ignore any locks set on the records that exist in the read view.

  • UPDATE ... WHERE ... sets an exclusive next-key lock on every record the search encounters.

  • DELETE FROM ... WHERE ... sets an exclusive next-key lock on every record the search encounters.

  • INSERT sets an exclusive lock on the inserted row. This lock is an index-record lock, not a next-key lock (that is, there is no gap lock) and does not prevent other sessions from inserting into the gap before the inserted row.

InnoDB has several types of record-level locks:

  • Record lock: This is a lock on an index record.

  • Gap lock: This is a lock on a gap between index records, or a lock on the gap before the first or after the last index record.

  • Next-key lock: This is a combination of a record lock on the index record and a gap lock on the gap before the index record.

See More :

Avoiding the Phantom Problem Using Next-Key Locking

Avoiding deadlock

魔法唧唧 2025-01-14 07:33:57

ypercube 说得对。具体来说,如果条件中没有使用唯一索引,它将锁定不止受影响的单行。

要查看您期望的行为,请将表创建更改为:

create table simple (col int unique) ENGINE=InnoDB;

col 字段上的唯一索引将允许它仅锁定受影响的行。

ypercube has it right. Specifically, without a unique index that's used in the condition, it will lock more than the single row being affected.

To see the behavior you expect, change your table creation to this:

create table simple (col int unique) ENGINE=InnoDB;

The unique index on the col field will allow it to lock only the affected row.

Bonjour°[大白 2025-01-14 07:33:57

“对于搜索遇到的索引记录,SELECT ... FROM ... FOR UPDATE 会阻止其他会话执行 SELECT ... FROM ... LOCK IN SHARE MODE 或在某些事务隔离级别中读取。一致性读取将忽略任何锁定设置在读取视图中存在的记录上”

可以通过 select for update 应用哪些特定锁定,以便其他会话无法读取锁定的记录?

"For index records the search encounters, SELECT ... FROM ... FOR UPDATE blocks other sessions from doing SELECT ... FROM ... LOCK IN SHARE MODE or from reading in certain transaction isolation levels. Consistent reads will ignore any locks set on the records that exist in the read view"

What are those certain locks which can be applied with select for update so that other sessions cannot read locked record?

蓝颜夕 2025-01-14 07:33:57

UPDATE ... WHERE ... 对搜索遇到的每个记录设置独占的下一键锁定。但是,对于使用唯一索引锁定行来搜索唯一行的语句,只需要索引记录锁。
所以在这种情况下,你期望一个索引记录锁,但是,你的索引不是唯一索引,所以你的语句将被添加一个独占的next-key锁。

UPDATE ... WHERE ... sets an exclusive next-key lock on every record the search encounters. However, only an index record lock is required for statements that lock rows using a unique index to search for a unique row.
So in this case, you expect an index record lock, however, your index is not unique index, so your statement will be added an exclusive next-key lock .

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文