一、問題複現
檔案/tmp/data.sql中兩列,每列一個數字1;
輸入
create table `t` (
`id` int(10) unsigned not null auto_increment,
`k` int(10) unsigned not null default '0',
primary key (`id`)
) engine=innodb auto_increment=1 default charset=utf8;
load data infile '/tmp/data.sql' into table t(k);
show create table t;
結果:
) engine=innodb auto_increment=4 default charset=utf8
二、原因分析
我們知道在5.1.22在之後,innodb為了解決自增主鍵鎖表的問題,引入了參數innodb_autoinc_lock_mode。這個值為0時,每次申請自增主鍵時需要鎖表。
這個參數的預設值是1,設為此值時,每次會“預申請”多餘的id(handler.cc: compute_next_insert_id),而insert執行完成後,會特别将這些預留的id空出,動作就是特意将預申請後的目前最大id回寫到表中(dict0dict.c:dict_table_autoinc_update_if_greater)。
三、簡單計算預留
注意這個預留的政策是“不夠時多申請幾個”, 實際執行中是分步申請。至于申請幾個,是由當時“已經插入了幾條資料n”決定的。當auto_increment_offset=1時,預申請的個數是 n-1。
是以會發現,當data.sql中隻有一行時,你看不到這個現象,并不預申請。
而當有兩行時(如文章開頭的例子),則需要。多申請的數目為1,是以執行後的自增值為4 (1+2+1)。
若data.sql中有三行呢?由于執行第三行的id已經在執行第二行時預留了,是以直接使用,結果的自增值仍為4。
後續的就類推了,可自行分析下。
實際insert行
自增id增加值
2、3
3
4、5、6、7
7
8~15
15