重复键更新时插入的线程安全性

问题描述 投票:0回答:1
MySQL声明:

INSERT ... ON DUPLICATE KEY UPDATE ...



看起来像一个应该是线程安全的单个语句(从某种意义上说,在其执行期间不会发生对同一数据的并发查询)。但另一方面,它可以在内部分解为

insert

update
 语句,我想知道它是否仍然保证线程安全? 

我的意思是,例如,在

delete

insert
 之间是否可能有一个 
update
 来自并发线程,导致 
update
 失败? 

我认为

insert on duplicate key update

应该是线程安全的,但文档似乎没有以明文形式说明。有人可以提供有关该主题的证明链接吗?内部是如何实现的?

mysql concurrency
1个回答
7
投票
RDBMS 使用锁和隔离级别来控制并行运行的会话如何访问相同的数据。不存在线程安全这样的东西,也不存在会话安全这样的东西。只有并发控制。

如果使用MyISAM表类型,那么所有数据修改语句

都会锁定整个表(MyISAM可以在有限的情况下进行并发插入,但删除确实需要始终锁定表)。因此,删除不会干扰 insert ... on duplicate key update...

如果使用InnoDB表类型,那么情况会稍微复杂一些,因为它应用了行级锁。正如MySQL手册上所说的

各种SQL语句设置的锁

INSERT ... ON DUPLICATE KEY UPDATE 与简单 INSERT 的不同之处在于,当发生重复键错误时,将在要更新的行上放置独占锁而不是共享锁。对重复的主键值采用独占索引记录锁定。对重复的唯一键值采取独占的下一键锁定。

因此,首先MySQL会锁定插入的新记录。如果出现重复键错误,只有此时重复记录才会被锁定。从技术上讲,在重复键错误和在重复记录上放置排他锁之间,删除语句可能会删除重复记录。但是,这不会使更新语句失败。它根本不会更新任何记录。

但这需要非常准确的删除语句时间。

仅当删除语句在重复键错误后获取重复记录上的排他锁并持有该锁的时间长到插入事务超时时,

insert ... on duplicate key update...

语句才可能失败。

© www.soinside.com 2019 - 2024. All rights reserved.