我正在两个不同的事务中尝试这些查询:
START TRANSACTION;
DELETE FROM `StopHistory` WHERE `deviceId` = 34;
START TRANSACTION;
SELECT id FROM `StopHistory` WHERE deviceId = 33 AND endAt > '2018-06-18 17:01:32.473';
第二个查询等待,因为第一个查询正在endEnd字段上创建锁。
MySQL [(none)]> select * from INFORMATION_SCHEMA.INNODB_LOCKS;
+-----------------------+-------------+-----------+-----------+--------------------------+------------+------------+-----------+----------+--------------------------+
| lock_id | lock_trx_id | lock_mode | lock_type | lock_table | lock_index | lock_space | lock_page | lock_rec | lock_data |
+-----------------------+-------------+-----------+-----------+--------------------------+------------+------------+-----------+----------+--------------------------+
| 104222007:699:1035:16 | 104222007 | S | RECORD | `db`.`StopHistory` | endAt | 641 | 1035 | 16 | 0x99A026D21307DA, 115347 |
| 104221958:699:1035:16 | 104221958 | X | RECORD | `db`.`StopHistory` | endAt | 641 | 1035 | 16 | 0x99A026D21307DA, 115347 |
+-----------------------+-------------+-----------+-----------+--------------------------+------------+------------+-----------+----------+--------------------------+
---TRANSACTION 104231466, ACTIVE 3 sec fetching rows
mysql tables in use 1, locked 1
LOCK WAIT 4 lock struct(s), heap size 376, 3 row lock(s)
MySQL thread id 59556, OS thread handle 0x2b1375f03700, query id 20584248 172.31.2.181 db Sending data
SELECT id FROM `StopHistory` WHERE deviceId = 33 AND endAt > '2018-06-18 17:01:32.473'
------- TRX HAS BEEN WAITING 3 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 641 page no 1035 n bits 16 index `endAt` of table `db`.`StopHistory` trx id 104231466 lock mode S waiting
Record lock, heap no 16 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
0: len=7; bufptr=0x2b134db1c16c; hex= 99a026d21307da; asc & ;;
1: len=4; bufptr=0x2b134db1c173; hex= 8001c293; asc ;;
------------------
---TRANSACTION 104231429, ACTIVE 11 sec
44 lock struct(s), heap size 376, 3103 row lock(s), undo log entries 1549
MySQL thread id 59555, OS thread handle 0x2b1375f03700, query id 20584210 172.31.2.181 db delayed send ok done
StopHistory
表在deviceId上有一个外键,在endAt上有一个索引
CREATE TABLE `StopHistory` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`endAt` datetime(3) DEFAULT NULL,
`deviceId` int(11) DEFAULT NULL,
`beginAt` datetime(3) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_StopHystory_2_idx` (`deviceId`),
KEY `beginAt` (`beginAt`),
KEY `endAt` (`endAt`),
KEY `device_beginAt` (`deviceId`,`beginAt`),
CONSTRAINT `fk_StopHystory_2` FOREIGN KEY (`deviceId`) REFERENCES `Devices` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=115351 DEFAULT CHARSET=utf8;
说明的输出:
MySQL [db]> explain DELETE FROM `StopHistory` WHERE `deviceId` = 34 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: StopHistory
type: range
possible_keys: PRIMARY,fk_StopHystory_1_idx,fk_StopHystory_2_idx,fk_StopHistory_1_idx,beginAt,endAt,device_beginAt
key: fk_StopHystory_2_idx
key_len: 5
ref: NULL
rows: 1548
Extra: Using where
为什么endAt字段被锁定?
答案 0 :(得分:0)
要对此SELECT
进行帮助,并可能减少锁定的机会,请更改
KEY `fk_StopHystory_2_idx` (`deviceId`),
收件人
KEY(deviceId, endAt)
此外,请注意,34紧接在33之后。因此删除所有34就是在33之后触摸“间隙”。这可能是导致锁争用的不可避免原因。
还请注意,DELETE
需要从3个BTree(主要的BTree)中删除项目,再加上从deviceId
开始的两个索引。大概后两者将通过“更改缓冲区”,并且不会太关键。