MySQL/MariaDB:SELECT 查询可以阻止 INSERT 查询吗?

Vil*_*lx- 3 mysql mariadb insert locking blocking

假设我有一个以下形式的查询:

INSERT INTO tableA (...) select ... from tableB;
Run Code Online (Sandbox Code Playgroud)

现在,这个查询在执行时是否有可能阻止普通INSERT语句tableB?附加信息:

  • 所有表都是InnoDB
  • 没有显式事务(自动提交已打开)
  • FOR UPDATE语句中没有子句SELECT(我什至不确定是否可以在INSERT...SELECT构造中做到这一点)
  • 实际的 SELECT 查询显然更复杂,涉及分组和联合,但这些不应该改变任何东西,对吧?
  • 所有查询的事务隔离级别是默认的REPEATABLE READ
  • 准确的数据库版本是MariaDB 10.0.12

Bil*_*win 5

是的,SELECT在这种情况下是锁定选择。

如果您SELECT在任何更改数据的查询中使用,它隐式是一个锁定查询,就像您使用过一样SELECT ... LOCK IN SHARE MODE。这会在它读取的行上放置一个共享锁。

任何其他更改数据的语句的行为方式相同。这包括以下情况:

  • INSERT ... SELECT ...
  • CREATE TABLE ... AS SELECT ...
  • SELECT ... INTO variable或者... INTO OUTFILE
  • SET @variable = (SELECT ...)
  • INSERT//上UPDATE的触发器在其主体中DELETE运行 a SELECT
  • UPDATEorDELETE语句中的子查询
  • 其他情况...

共享锁可以由多个并发会话持有。所以你可以INSERT ... SELECT在多个事务中执行此查询。他们不会互相冲突。

INSERT对tableB必须有独占锁。如果存在任何共享锁,则不会授予独占锁。

  • 例如 https://mariadb.com/kb/en/triggers-and-implicit-locks/ 和 https://dev.mysql.com/doc/refman/8.0/en/innodb-locks-set.html。 (2认同)
  • 另请参阅 7 年前的另一篇文章,同样由 Bill Karwin 撰写。我个人首选的解决方案是“解决方法”标题下的解决方案:/sf/answers/1667187931/ (2认同)