mysql - MySQL Query 是否包含子查询原子?

标签 mysql

有两个表:

表 1 独特 session

ID    Count 

表 2( session )

ID    Name

只有当 name 不存在于 session 中时,我才想更新 count 以计算唯一 session ,这是一个示例,因此目标不是通过其他方式进行,但问题是:

Rowsaffected = Update table1 
                   set Count = Count + 1 
               where (Select count(*) from table2 where Name = 'user1' ) = 0;

Insert into table2 (NAME) values('user');

first query 是原子查询吗?如果是,则没有问题。

如果不是,那么如果有多个线程运行来执行上述操作怎么办?有可能:

线程 1:count 返回 0,它在线程 2 启动之前更新了表 1 但没有更新表 2。 线程 2:它找到计数 0,它也将更新计数。

现在对于同一个用户,计数是 2,这是不应该发生的。

任何建议/反馈。

最佳答案

最好使用 exists 子句: https://dev.mysql.com/doc/refman/8.0/en/exists-and-not-exists-subqueries.html

Rowsaffected = Update table1 set Count = Count + 1 where NOT EXISTS (Select ID from table2 where Name = 'user1' );

仅针对您问题的原子部分的引用,但可以肯定的是,您可以将这两个语句包装在一个事务中。 虽然根据您的并发模型,您可能希望考虑提高事务隔离级别,但这看起来并不是绝对必要的。

MySQL 将语句视为原子 https://dev.mysql.com/doc/refman/8.0/en/mysql-acid.html

从技术上讲,子查询是它们出现的语句的一部分。 https://dev.mysql.com/doc/refman/8.0/en/expressions.html 尽管在语法上类似于独立语句,但它们是单独运行的 - 优化器将整个语句视为一个工作单元。

这确实假设您正在使用支持事务的存储引擎: https://dev.mysql.com/doc/refman/8.0/en/storage-engines.html (在页面底部的表格末尾)

隔离级别要求在查询运行时获取的读锁将一直保留,直到获取了写锁并且所有锁将一起释放。 https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html

(尽管文档似乎没有明确说明这一点,否则它无法保证隔离级别)

关于mysql - MySQL Query 是否包含子查询原子?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5816062/

相关文章:

php - 使用 Wamp 服务器命令在 Windows 上关闭命令提示符

php - 使用 PHP 和 mysqli 从数据库中排除以前的值

mysql - mysql中where条件多的sql是否比mysql中条件少的sql快?

mysql - 最佳使用数据库存储大型科学数据集

mysql - Coldfusion 中的慢速加密

php - Valum php AJAX 上传 : Store File Name and Path into mySQL database

php - 检查与您的 MySQL 服务器版本对应的手册,了解在第 1 行 '' 附近使用的正确语法

mysql - 卸载MySQL后如何设置3306端口空闲?

php - "Query"PHP 中的数组

android - 何时使用 CREATE INDEX 以及何时使用 USE INDEX