Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/71.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
sql何时以独占方式锁定update语句中的行?_Sql_Multithreading_Synchronization - Fatal编程技术网

sql何时以独占方式锁定update语句中的行?

sql何时以独占方式锁定update语句中的行?,sql,multithreading,synchronization,Sql,Multithreading,Synchronization,在这些条件下,sql中是否会出现竞争条件 如果在一个线程中运行此SQL更新,请将其称为语句1: Update Items Set Flag = B where Flag = A; 此SQL更新运行在另一个call it语句2中: Update Items Set Flag = C where Flag = A; 每个线程是否可以读取标志等于A的同一条记录,并使用自己的值写入该记录?这样,语句1可以先写,然后语句2再写,或者反之亦然 这个问题的答案取决于数据库何时以独占方式锁定更新。它是在找到

在这些条件下,sql中是否会出现竞争条件

如果在一个线程中运行此SQL更新,请将其称为语句1:

Update Items
Set Flag = B
where Flag = A;
此SQL更新运行在另一个call it语句2中:

Update Items
Set Flag = C
where Flag = A;
每个线程是否可以读取标志等于A的同一条记录,并使用自己的值写入该记录?这样,语句1可以先写,然后语句2再写,或者反之亦然


这个问题的答案取决于数据库何时以独占方式锁定更新。它是在找到记录之前还是在找到记录并计算where子句之后发生的?

用于数据修改操作(如插入、更新或删除)的独占锁将在此场景中使用

独占锁确保不能同时对同一资源进行多个更新

在这种情况下,您将不会获得竞争条件

如果您有一个涉及多个表的更复杂的场景,那么您可能会遇到竞争条件或死锁。有许多方法可以避免这种情况,例如简化和分离查询等

您还可以对查询应用提示,告诉SQL使用哪种类型的锁


听起来您应该阅读有关锁定的内容。SQL server有一组复杂的逻辑,将根据估计需要更新的行数执行表级或行级锁定。除非您明确地告诉它您希望它执行哪一个,否则它甚至可能因查询而异。通常,如果修改表的一小部分,它将选择行级锁

SQL Server在设计时考虑到了ACID,因此在对数据执行任何实际更新之前,它会将更改写入日志。这允许回滚任何失败的更新,并允许查询之间保持一致性(如询问)。您可以执行脏读来绕过锁定问题,但不能阻止SQL Server锁定插入、更新和/或删除的记录

编辑:这是一篇关于ACID的文章。

所有SQL数据库几乎都保证不会发生这种冲突。发生“何时”锁定取决于锁定是在表、分区、页还是行级别。或者,您是否已关闭数据库中的此类锁定

如果您有并发的update语句,并且有多行正在更新,那么会发生这样的情况:一行使用第一行更新,另一行使用第二行更新

通常,我认为where子句的计算目的是选择行集,一次锁定一行,执行更新和解锁。但是,这取决于锁定的类型。在这种情况下,上述场景将继续进行值翻转


如果您担心这种情况,请在处理并发更新请求时使用表级锁定强制序列化。

首先,有三种锁定上下文:

  • 数据库级锁
  • 桌位锁
  • 行级锁
然后有四种锁定模式:

  • X
IX和IS锁是“意向”锁。在获取其他类型的锁之前,先持有这些锁。X锁是独占(写)锁,S锁是共享(读)锁

锁(IX、IS、X或S)可以在任何上下文级别使用。例如,数据库级别的X锁将阻止数据库中的所有其他操作。这是SQLlite使用的锁的类型。在读取期间对整个数据库使用S锁,在写入期间对整个数据库使用X锁。写入将等待任何S锁完成,并将阻止新的S锁和X锁,直到释放写入锁。这提供了一个可序列化的隔离事务级别

对于MySQL,锁定取决于存储引擎。MyISAM将在整个(一组)表上使用X和S锁。X锁将等待现有的S或X锁并阻止新锁。新的X锁将在队列中获得更高的优先级,移动到新的S锁之前。可以通过设置低优先级更新来更改此行为,这可能会导致写饥饿,因为写操作将被取消优先级,以利于读取

在MySQL中,可以使用“带读锁的刷新表”在整个数据库上获得X锁

InnoDB锁定通过索引读取遇到的行。InnoDB锁定索引记录,并在遍历索引记录时锁定这些记录。InnoDB使用称为“间隙”锁的特殊锁来确保可重复读取事务隔离级别。锁保存在索引项上,因此如果一个表没有很好地为更新查询建立索引,那么许多行将被锁定。请注意,InnoDB不会为正常的SELECT查询创建S锁。对于一致的快照,它使用行版本控制,而不是行级别锁定

获取X锁时,数据库需要检测死锁。考虑以下事项:

>connection 1
start transaction;
update T set c = c + 1 order by id asc;

>connection 2
start transaction;
update T set c = c - 1 order by id desc;
在行锁定模型中,这两条语句不能同时成功完成。第一个将永远等待获得第二个持有的锁,反之亦然。数据库将选择一个要回滚的连接。InnoDB将选择更改次数最少的连接。MyISAM将为首先获得锁的连接锁定整个表,然后在第一个连接完成后运行第二个连接

您给出的简单示例将由任意上下文(数据库、表或行)上的X锁解析。如果两个连接以完全相同的类型开始,并且都运行两个试图更新同一行的更新,则都将尝试获取X锁。只有一个连接可以获取X锁。无法准确确定哪一个将获得锁。另一个连接必须等待锁被释放,直到它可以获得X锁。请记住,如果行被删除或更新锁定,t