繁体   English   中英

InnoDB在没有插入或更新操作待处理的表上放置锁

[英]`InnoDB` placing a lock on a table that has no `insert` or `update` operations pending

我目前有一个漫长的过程,该过程将表A的行插入到AB之间的复杂联接查询中。 自此过程开始以来,对表B所有insert操作都已超时。 这是我执行SHOW ENGINE INNODB STATUS

---TRANSACTION 3597993, ACTIVE 108 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 173507, OS thread handle 140455303333632, query id 1051475 10.0.0.6 root update
INSERT INTO `B` (`id`, `time`, `elem_1`, `elem_2`) VALUES (251322486, '2018-04-27 19:29:59', 'PTY', 'USD')
------- TRX HAS BEEN WAITING 108 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 6 page no 5859 n bits 96 index PRIMARY of table `default`.`B` trx id 3597993 lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;

我对InnoDB规则的理解是,不应在B发生锁定,因为唯一正在运行的进程是从中读取它,而不是更新或插入。

正在进行的插入操作具有以下结构:

insert into `default`.A
select * from (select i1.id, min(IFNULL(i2.id,-1)) as next_id, i1.item_1, i1.item_2 from
(select idx.id, idx.item_2, idx.item_2
 from `default`.B idx left join `default`.A map on
idx.id = map.id and idx.item_1 = map.item_1 where map.id is null or map.next_id = -1) i1 left join
`default`.B i2 on i1.id < i2.id and i1.item_1 = i2.item_1 and i1.item_2 = i2.item_2
group by i1.id, i1.item_1, i1.item_2) new_entries
on duplicate key update next_id = new_entries.next_id

这是我正在使用的数据库的版本:

mysql> SHOW VARIABLES LIKE "%version%";
+-------------------------+--------------------------------------+
| Variable_name           | Value                                |
+-------------------------+--------------------------------------+
| innodb_version          | 5.7.21                               |
| protocol_version        | 10                                   |
| slave_type_conversions  |                                      |
| version                 | 10.2.13-MariaDB-10.2.13+maria~jessie |
| version_comment         | mariadb.org binary distribution      |
| version_compile_machine | x86_64                               |
| version_compile_os      | debian-linux-gnu                     |
| version_malloc_library  | system                               |
| version_ssl_library     | OpenSSL 1.0.1t  3 May 2016           |
| wsrep_patch_version     | wsrep_25.21                          |
+-------------------------+--------------------------------------+

UPDATE

我停止了长期的操作并重新启动了它,现在插入似乎没有受到阻碍,因此我倾向于考虑这个临时错误

如果您使用SELECT的结果以某种方式将数据保存到表或变量中,那么InnoDB确实会在您选择的表中的行上创建共享锁。

INSERT INTO T1 SELECT ... FROM T2 ...;

CREATE TABLE T1 AS SELECT ... FROM T2 ...;

SET @my_variable = (SELECT ... FROM T2 ...);

SELECT ... INTO @my_variable, ... FROM T2 ...;

在上述所有情况下,T2中的行都将获得共享锁。 共享意味着多个并发语句可以在同一行上拥有共享锁,但是当这些行上存在任何共享锁时,任何并发语句都不能在一组行上获得排他锁。

参见https://dev.mysql.com/doc/refman/8.0/en/innodb-locks-set.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM