MYSQL培训准备(2):MYSQL自增长陷阱
MYSQL中,在数据库中创建表的语法如下:
1 CREATE TABLE tablename( 2 column_name_1 column_type_1 constraints, 3 column_name_2 column_type_2 constraints, 4 ... 5 column_name_n column_type_n constraints, 6 PRIMARY KEY (column_name) 7 );
其中,tablename为表名,column_name为列名,column_type为列的数据类型,constraints为相关的约束条件。在所有的约束条件中,有一个AUTO_INCREMENT的条件,表示自增长列,根据设置的步长自动增长。
今天我们聊聊MYSQL中的自增长列。
在MS SQL SERVER中,我们知道自增长列是严格按照步长实现自动增长。而MYSQL中却有个则增长的陷阱。对于单条记录,一条一条insert into,确实是自增长的。但如果我们批量插入,自增长列就不是连续的。请看下面实例。
首先,我们创建一张部门表,语句如下:
CREATE TABLE `ivr`.`t_dept` ( `f_id` INT Not NULL AUTO_INCREMENT, `f_areaid` INT NULL, `f_dept` VARCHAR(45) NULL, PRIMARY KEY (`f_id`));
当我们逐条插入数据时,自增长列是连续的。如下:
insert into t_dept(f_areaid,f_dept) values(2,'网优' ); insert into t_dept(f_areaid,f_dept) values(2,'传输' ); insert into t_dept(f_areaid,f_dept) select 2,'数据'; insert into t_dept(f_areaid,f_dept) select 2,'家宽';
查询结果如下:
mysql> select * from t_dept; +------+----------+--------+ | f_id | f_areaid | f_dept | +------+----------+--------+ | 1 | 2 | 网优 | | 2 | 2 | 传输 | | 3 | 2 | 数据 | | 4 | 2 | 家宽 | +------+----------+--------+ 4 rows in set (0.00 sec)
当我们批量插入时,问题就出现了,请看下面:
insert into t_dept(f_areaid,f_dept) select 3,'网优' union select 3,'传输';
结果如下:
mysql> select * from t_dept; +------+----------+--------+ | f_id | f_areaid | f_dept | +------+----------+--------+ | 1 | 2 | 网优 | | 2 | 2 | 传输 | | 3 | 2 | 数据 | | 4 | 2 | 家宽 | | 5 | 3 | 网优 | | 6 | 3 | 传输 | +------+----------+--------+ 6 rows in set (0.00 sec)
此时f_id还是连续的。当我们再插入记录时,问题出现的。
insert into t_dept(f_areaid,f_dept) select 3,'数据' union select 3,'家宽' ;
我们再看结果,7不见了:
mysql> select * from t_dept; +------+----------+--------+ | f_id | f_areaid | f_dept | +------+----------+--------+ | 1 | 2 | 网优 | | 2 | 2 | 传输 | | 3 | 2 | 数据 | | 4 | 2 | 家宽 | | 5 | 3 | 网优 | | 6 | 3 | 传输 | | 8 | 3 | 数据 | | 9 | 3 | 家宽 | +------+----------+--------+ 8 rows in set (0.00 sec)
为什么会出现这种情况呢,我查看了手册,MYSQL中,自增长列只保证字段的唯一性。当批量插入n条记录时,MYSQL需要n-1条记录缓存,此时会默认为插入了2n-1条记录,从而造成了记录的不连续性。