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;```
## 自增值
```go
INSERT INTO t VALUES (null,1,1);
-- AUTO_INCREMENT=2,表示下一次插入数据时,如果需要自动生成自增值,会生成id=2
mysql> SHOW CREATE TABLE t;
+-------+---------------------------------------------+
| Table | Create Table |
+-------+---------------------------------------------+
| t | 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 AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 |
+-------+---------------------------------------------+
-- 采用双M架构是,auto_increment_increment设置为2,避免两个库生成的主键冲突
mysql> SELECT @@auto_increment_offset;
+-------------------------+
| @@auto_increment_offset |
+-------------------------+
| 1 |
+-------------------------+
mysql> SELECT @@auto_increment_increment;
+----------------------------+
| @@auto_increment_increment |
+----------------------------+
| 1 |
+----------------------------+
mysql> INSERT INTO t VALUES (null,1,1);
ERROR 1062 (23000): Duplicate entry '1' for key 'c'
-- id没有回退
mysql> SHOW CREATE TABLE t;
+-------+---------------------------------------------+
| Table | Create Table |
+-------+---------------------------------------------+
| t | 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 AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 |
+-------+---------------------------------------------+
mysql> INSERT INTO t VALUES (null,2,2);
Query OK, 1 row affected (0.16 sec)
-- id不连续
mysql> SELECT * FROM t;
+----+------+------+
| id | c | d |
+----+------+------+
| 1 | 1 | 1 |
| 3 | 2 | 2 |
+----+------+------+
truncate table t;
INSERT INTO t VALUES (null,1,1);
BEGIN;
INSERT INTO t VALUES (null,2,2);
ROLLBACK;
INSERT INTO t VALUES (null,2,2);
-- id不连续
mysql> SELECT * FROM t;
+----+------+------+
| id | c | d |
+----+------+------+
| 1 | 1 | 1 |
| 3 | 2 | 2 |
+----+------+------+
-- MySQL 5.6
mysql> SELECT @@innodb_autoinc_lock_mode;
+----------------------------+
| @@innodb_autoinc_lock_mode |
+----------------------------+
| 1 |
+----------------------------+
默认配置下,INSERT…SELECT的自增锁是语句级别的,这是为了数据的一致性
假设session B是申请了自增值以后马上释放自增锁,并且binglog_format=STATEMENT
SessionA | SessionB |
---|---|
INSERT INTO t VALUES (null,1,1); |
|
INSERT INTO t VALUES (null,2,2); |
|
INSERT INTO t VALUES (null,5,5); |
|
INSERT INTO t VALUES (null,3,3); |
|
INSERT INTO t VALUES (null,4,4); |
|
CREATE TABLE t2 LIKE t; |
|
INSERT INTO t2(c,d) SELECT c,d FROM t; |
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;
-- 第一次申请id=1,第二次申请id=2~3,第三次申请id=4~7
INSERT INTO t2(c,d) SELECT c,d FROM t;
-- 实际插入为(8,5,5)
INSERT INTO t2 VALUES (null,5,5);
mysql> SELECT * FROM t2;
+----+------+------+
| id | c | d |
+----+------+------+
| 1 | 1 | 1 |
| 2 | 2 | 2 |
| 3 | 3 | 3 |
| 4 | 4 | 4 |
| 8 | 5 | 5 |
+----+------+------+
自增ID的生成顺序,和binlog的写入顺序可能是不相同的
SET binlog_format=STATEMENT;
CREATE TABLE t (id INT AUTO_INCREMENT PRIMARY KEY);
INSERT INTO t VALUES (null);
BEGIN
$ mysqlbinlog -vv ./binlog.000027
/*!*/;
# at 15720
# at 15752
#190319 22:35:13 server id 1 end_log_pos 15752 CRC32 0xf118154f Intvar
SET INSERT_ID=1/*!*/;
#190319 22:35:13 server id 1 end_log_pos 15856 CRC32 0x40050594 Query thread_id=28 exec_time=0 error_code=0
SET TIMESTAMP=1553006113/*!*/;
INSERT INTO t VALUES (null)
PS:参考mysql45讲