【发布时间】:2018-06-19 15:35:27
【问题描述】:
我正在两个不同的事务中尝试这些查询:
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';
第二个查询等待,因为第一个查询在 endAt 字段上创建一个锁。
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 字段被锁定?
【问题讨论】:
-
我猜删除并没有影响外键关系更改,因此 InnoDB 引擎没有锁定外键索引记录,以将所有外键关系记录的性能和可访问性保持在其他查询的最大值...因此,Devices 表中的 DELETE 应该锁定外键索引记录
标签: mysql transactions locking mariadb innodb