Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 使用WHERE为NULL和LIMIT执行更新时可能发生冲突?_Mysql_Sql - Fatal编程技术网

Mysql 使用WHERE为NULL和LIMIT执行更新时可能发生冲突?

Mysql 使用WHERE为NULL和LIMIT执行更新时可能发生冲突?,mysql,sql,Mysql,Sql,假设我有下表: | id | claimed | ---------------- | 1 | NULL | | 2 | NULL | | 3 | NULL | 我可以执行此查询来准确地(任意)更新其中一行,而无需先执行select UPDATE mytable SET claimed=[someId],其中claimed为空限制1 但是,如果此查询的两个并发请求发生,会发生什么情况。后面的请求是否可以覆盖第一个请求的值?我知道发生这种情况的可能性很小,但仍然存在。执行

假设我有下表:

| id | claimed |
----------------
| 1  | NULL    |
| 2  | NULL    |
| 3  | NULL    |
我可以执行此查询来准确地(任意)更新其中一行,而无需先执行select

UPDATE mytable SET claimed=[someId],其中claimed为空限制1


但是,如果此查询的两个并发请求发生,会发生什么情况。后面的请求是否可以覆盖第一个请求的值?我知道发生这种情况的可能性很小,但仍然存在。

执行语句
updatemytableset=[someId]其中声明为空,事务
t1
中的限制1
锁定相应记录,并防止任何其他事务
t2
更新同一记录,直到事务
t1
提交(或中止)。交易
t2
同时被阻塞
t2
继续一次
t1
提交(或中止),或者
t2
在达到超时后自动中止

授予:

MySQL对InnoDB表使用行级锁定来支持同步 通过多个会话进行写访问,使其适合 多用户、高并发和OLTP应用程序

以及:

更新。。。哪里在每条记录上设置独占的下一个密钥锁 搜索遭遇。但是,只需要索引记录锁 对于使用唯一索引锁定行以搜索 唯一行

最后是mysql引用InnoDB锁定记录锁中的锁定行为:

如果事务T1在r行上持有独占(X)锁,则请求 从某个不同的事务T2获取r上任意一种类型的锁 不能立即批准。相反,事务T2必须等待 事务T1释放其对行r的锁定

因此,只要这两个查询在不同的事务中运行,它们就不会获取相同的记录

请注意,完整记录已锁定,因此其他事务的其他更新操作将被阻止,即使它们将更新相应记录的其他属性

我使用SequelPro进行了试用,您可以在任何客户机上试用,如下所示:

  • 确保mytable至少包含两条声明了
    的记录
    为空
  • 打开两个连接窗口/端子;让我们称他们为c1和
    c2
  • c1
    中,执行以下两个命令:
    start transaction;
    更新mytable SET claimed=15,其中claimed为空限制1#
    到目前为止还没有承诺
  • c2
    中,执行类似的命令(注意
    索赔
    ):
    启动交易;UPDATE mytable SET claimed=16,其中claimed为空限制1;#同样,到目前为止没有提交
  • 窗口
    c2
    应通知您它正在工作(即等待 要完成的查询)
  • 切换到窗口
    c1
    并执行命令
    commit
  • 切换到窗口
    c2
    ,此时(以前启动的)查询应 现在已经完成了;执行
    commit
  • 查看
    mytable
    时,一条记录现在应该具有
    claim=15
    , 另一个应该有
    索赔=16

  • 您在数据库中输入的最后一个值是粘贴的值,这是应该发生的。是的。但是在这种情况下,它是
    其中声明为NULL
    ,而不是例如
    其中id=3
    。它会尝试更新同一行吗?
    update
    操作是原子的,因此在正确实现的DBMS中不应该发生这种情况。