基于语句级别的复制,当 innodb_autoinc_lock_mode = 0 | 1 时,主从使用的是相同的自增列值。当 innodb_autoinc_lock_mode = 2 或者主从使用不同的 innodb_autoinc_lock_mode 时,主从无法保证使用相同的自增列值;
基于行级别和复合模式的复制,innodb_autoinc_lock_mode 的所有取值都是安全的,因为SQL语句执行顺序对基于行级别的复制没影响。
自增值缺失与间隙无论 AUTO_INCREMENT 处于哪种锁模式下,即 innodb_autoinc_lock_mode 的所有取值情况下,在一个事务当中自增列分配的值是不能被回滚的。这会导致事务回滚了,但是自增列分配的值却消失了,自增列分配的值是无法随着事务回滚而重复利用,这样就自增列上的值就产生了间隙。
测试:
--1、 开启一个事务 (root@localhost) [test] > begin; Query OK, 0 rows affected (0.00 sec) (root@localhost) [test] > insert into t1(c2) values('aa'); Query OK, 1 row affected (0.00 sec) (root@localhost) [test] > select * from t1; +----+------+ | c1 | c2 | +----+------+ | 1 | aa | +----+------+ 1 row in set (0.00 sec) (root@localhost) [test] > show create table t1\G; *************************** 1. row *************************** Table: t1 Create Table: CREATE TABLE `t1` ( `c1` int(11) NOT NULL AUTO_INCREMENT, `c2` varchar(10) DEFAULT NULL, PRIMARY KEY (`c1`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 1 row in set (0.00 sec) --2、事务回滚,不提交 (root@localhost) [test] > rollback; Query OK, 0 rows affected (0.00 sec) (root@localhost) [test] > select * from t1; Empty set (0.00 sec) (root@localhost) [test] > show create table t1\G; *************************** 1. row *************************** Table: t1 Create Table: CREATE TABLE `t1` ( `c1` int(11) NOT NULL AUTO_INCREMENT, `c2` varchar(10) DEFAULT NULL, PRIMARY KEY (`c1`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 1 row in set (0.00 sec) --3、再次开启事务,插入值并提交 (root@localhost) [test] > begin; Query OK, 0 rows affected (0.00 sec) (root@localhost) [test] > insert into t1(c2) values('aaa'); Query OK, 1 row affected (0.02 sec) (root@localhost) [test] > select * from t1; +----+------+ | c1 | c2 | +----+------+ | 2 | aaa | +----+------+ 1 row in set (0.00 sec) (root@localhost) [test] > commit; Query OK, 0 rows affected (0.00 sec) (root@localhost) [test] > show create table t1\G; *************************** 1. row *************************** Table: t1 Create Table: CREATE TABLE `t1` ( `c1` int(11) NOT NULL AUTO_INCREMENT, `c2` varchar(10) DEFAULT NULL, PRIMARY KEY (`c1`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 1 row in set (0.00 sec)可以看出自增列分配的值是不会再出现 c1=1 的。
为自增列指定NULL或者0无论 AUTO_INCREMENT 处于哪种锁模式下,如果在 INSERT 语句为自增列指定 NULL 或者 0 时,InnoDB认为并没有为自增列指定值,同时也会为其分配值。
测试:
(root@localhost) [test] > select * from t1; +----+------+ | c1 | c2 | +----+------+ | 2 | aaa | +----+------+ 1 row in set (0.00 sec) (root@localhost) [test] > insert into t1 values(NULL,'bbb'),(0,'ccc'); Query OK, 2 rows affected (0.02 sec) Records: 2 Duplicates: 0 Warnings: 0 (root@localhost) [test] > select * from t1; +----+------+ | c1 | c2 | +----+------+ | 2 | aaa | | 3 | bbb | | 4 | ccc | +----+------+ 3 rows in set (0.00 sec) (root@localhost) [test] > show create table t1\G; *************************** 1. row *************************** Table: t1 Create Table: CREATE TABLE `t1` ( `c1` int(11) NOT NULL AUTO_INCREMENT, `c2` varchar(10) DEFAULT NULL, PRIMARY KEY (`c1`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 1 row in set (0.00 sec) 为自增列指定负值无论 AUTO_INCREMENT 处于哪种锁模式下,自增列分配值机制不会生效,即为自增列指定负值是不影响 AUTO_INCREMENT 值的。
测试:
(root@localhost) [test] > SELECT auto_increment FROM information_schema.tables where table_schema='test' and table_name='t1'; +----------------+ | auto_increment | +----------------+ | 5 | +----------------+ 1 row in set (0.00 sec) (root@localhost) [test] > insert into t1 values(-1,'ddd'); Query OK, 1 row affected (0.01 sec) (root@localhost) [test] > select * from t1; +----+------+ | c1 | c2 | +----+------+ | -1 | ddd | | 2 | aaa | | 3 | bbb | | 4 | ccc | +----+------+ 4 rows in set (0.00 sec) (root@localhost) [test] > SELECT auto_increment FROM information_schema.tables where table_schema='test' and table_name='t1'; +----------------+ | auto_increment | +----------------+ | 5 | +----------------+ 1 row in set (0.00 sec) 自增列值大于列类型最大的整型值无论 AUTO_INCREMENT 处于哪种锁模式下,自增列分配的值如果大于自增列所属字段类型的最大值,则自增列分配值机制就不会生效。