首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在MySQL中,为什么在使用读未提交时,从select中设置一个变量会获得一个锁?

在MySQL中,为什么在使用读未提交时,从select中设置一个变量会获得一个锁?
EN

Stack Overflow用户
提问于 2012-10-31 05:37:02
回答 1查看 1.5K关注 0票数 8

我们在MySQL中有一个使用InnoDB的表,我们使用的是未提交的事务隔离级别。为什么如图所示的设置@x会获得一个锁?

代码语言:javascript
复制
mysql> set @x = (select userID from users limit 1);
Query OK, 0 rows affected (0.02 sec)

mysql>

试图从另一个提示更新此表会导致超时错误:

代码语言:javascript
复制
mysql> update users set userID = 1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
EN

回答 1

Stack Overflow用户

发布于 2014-05-01 18:09:39

不管它的价值是什么,这种锁定并不局限于READ-UNCOMMITTED

代码语言:javascript
复制
mysql1> show variables like '%isolation%';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tx_isolation  | REPEATABLE-READ |
+---------------+-----------------+
mysql1> BEGIN;
mysql1> SET @x := (SELECT x FROM foo LIMIT 1);

mysql2> UPDATE foo SET x = x+1;
[gets a lock wait]

mysql3> SHOW ENGINE INNODB STATUS;
...
---TRANSACTION 228746, ACTIVE 22 sec
2 lock struct(s), heap size 360, 1 row lock(s)
MySQL thread id 58, OS thread handle 0x7fc262a1c700, query id 8163
  192.168.56.1 root cleaning up
TABLE LOCK table `test`.`foo` trx id 228746 lock mode IS
RECORD LOCKS space id 801 page no 3 n bits 80 index `PRIMARY` 
  of table `test`.`foo` trx id 228746 lock mode S
...

正如您所记录的错误错误#67452从select中设置一个变量,在使用read时获得一个锁中所讨论的那样,这种行为可能是由设计造成的。它似乎属于与SELECT语句相同的类别,这些语句的结果用于修改数据,如所描述的情况:

http://dev.mysql.com/doc/refman/5.6/en/innodb-locks-set.html

当在构造REPLACE INTO t SELECT ... FROM s WHERE ...UPDATE t ... WHERE col IN (SELECT ... FROM s ...)中使用SELECT时,InnoDB对表s中的行设置共享下键锁。

下一个键锁的原因是为了使SELECT结果更加稳定。也就是说,我们不希望SELECT匹配的行在用于UPDATE或其他数据修改语句时发生更改。

即使tx_isolation是REPEATABLE-READ,这也很重要,因为当SELECT语句作为任何类型的UPDATE的一部分执行时,InnoDB并不支持SELECT语句的REPEATABLE-READ

关于你的评论:

不管文档是什么,下面是发生的情况:

当您执行普通的SELECT语句时,InnoDB不会在除SERIALIZABLE之外的任何事务隔离中锁定任何东西。

如果您执行SELECT ... LOCK IN SHARE MODESELECT ... FOR UPDATE,它当然会锁定。

但是,当您将SELECT作为INSERT INTO...SELECT之类的数据修改语句的一部分,或者在UPDATE的子查询中,或者您在SET @variable := (SELECT...)中找到的时候,它使用共享锁来确保数据在更新过程中不会改变。

文件可能不完整。最好是测试一下。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13151837

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档