INSERT…SELECT
表初始化
CREATE TABLE `t` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`c` INT(11) DEFAULT NULL,
`d` INT(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `c` (`c`)
) ENGINE=InnoDB;
INSERT INTO t VALUES (null,1,1);
INSERT INTO t VALUES (null,2,2);
INSERT INTO t VALUES (null,3,3);
INSERT INTO t VALUES (null,4,4);
CREATE TABLE t2 LIKE t;
操作时序
时刻 | SessionA | SessionB |
---|---|---|
T1 | BEGIN; |
|
T2 | INSERT INTO t2(c,d) SELECT c,d FROM t; |
|
T3 | INSERT INTO t VALUES (-1,-1,-1);(Blocked) |
-- T3时刻
mysql> SELECT locked_index,locked_type,waiting_lock_mode,blocking_lock_mode FROM sys.innodb_lock_waits WHERE locked_table='`test`.`t`';
+--------------+-------------+-------------------+--------------------+
| locked_index | locked_type | waiting_lock_mode | blocking_lock_mode |
+--------------+-------------+-------------------+--------------------+
| PRIMARY | RECORD | X,GAP | S |
+--------------+-------------+-------------------+--------------------+
- T2时刻,session B会在表t加上PRIMARY:Next-Key Lock:(-∞,1]
- 如果没有锁的话,就可能会出现session B的INSERT语句先执行,但对应的binlog后写入的情况
- binlog_format=STATEMENT,binlog里面的语句序列如下
- INSERT INTO t VALUES (-1,-1,-1)
- INSERT INTO t2(c,d) SELECT c,d FROM t
- 这个语句传到备库执行,就会把id=-1这一行也会写到t2,主备不一致
- binlog_format=STATEMENT,binlog里面的语句序列如下
INSERT循环写入
非循环写入
mysql> EXPLAIN INSERT INTO t2(c,d) (SELECT c+1,d FROM t FORCE INDEX(c) ORDER BY c DESC LIMIT 1);
+----+-------------+-------+------------+-------+---------------+------