mysql - INSERT ON DUPLICATE KEY UPDATE 的线程安全

标签 mysql concurrency

MySQL语句:
INSERT ... ON DUPLICATE KEY UPDATE ...
看起来像一条应该是线程安全的语句(从某种意义上说,在执行期间不会发生对相同数据的并发查询)。但另一方面,它可以在内部分解为 insertupdate 语句,我想知道它是否仍然保证线程安全?

我的意思是,例如,在 deleteinsert 之间是否有来自并发线程的 update 会导致 update 失败?

我认为 insert on duplicate key update 应该是线程安全的,但文档似乎没有以明文形式说明它。任何人都可以提供有关该主题的证明链接吗?内部如何实现?

最佳答案

RDBMS 使用锁和隔离级别来控制并行运行的 session 如何访问相同的数据。没有线程安全这样的东西,也没有 session 安全。只有并发控制。

如果使用myisam表类型,那么所有的数据修改语句都是lock the entire table(myisam在有限的情况下可以并发插入,但是delete确实需要一直锁表)。因此,删除不能干扰 insert ... on duplicate key update...

如果使用 innodb 表类型,那么情况会稍微复杂一些,因为它应用了行级锁。正如 mysql 手册在 locks set by various sql statements 上所说:

INSERT ... ON DUPLICATE KEY UPDATE differs from a simple INSERT in that an exclusive lock rather than a shared lock is placed on the row to be updated when a duplicate-key error occurs. An exclusive index-record lock is taken for a duplicate primary key value. An exclusive next-key lock is taken for a duplicate unique key value.



因此,首先 mysql 锁定插入的新记录。如果发生重复键错误,则仅锁定重复记录。从技术上讲,在重复键错误和对重复记录放置排它锁之间,删除语句可能会删除重复记录。但是,这不会使更新语句失败。它不会更新任何记录。

但这需要非常准确的删除语句时间。
insert ... on duplicate key update... 语句可能仅在删除语句在重复键错误后获取对重复记录的排他锁并持有该锁的时间过长以至于插入的事务超时时才可能失败。

关于mysql - INSERT ON DUPLICATE KEY UPDATE 的线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45652775/

相关文章:

php - 如何在更新前检查另一个表?

java - 将任务从 EDT 分派(dispatch)到 main?

java - 同步部分不阻塞!

Java工厂方法缓存

java - 有没有一种简单的方法可以告诉 Java Executor 在给定时刻正在运行哪些任务?

c++ - 使用多线程优化执行时间(简单示例)

Mysql 按 y 列的字母顺序排列所有具有 null x 列的行,然后按 y 列的字母顺序排列所有没有 null x 列的行

php - 使用 PHP 和 Javascript 从 MySQL 拆分数据在 IE 中有效,但在 FF 中无效

php - Mysql中存储的特殊字符

python - 在 django ORM 中获取注释内的列表