問題重現
先從問題入手,重現下這個bug
use test;這裡我們關閉mysql,再啟動mysql,然後再插入一條資料drop table if exists t1;
create table t1(id int auto_increment, a int, primary key (id)) engine=innodb;
insert into t1 values (1,2);
insert into t1 values (null,2);
insert into t1 values (null,2);
select * from t1;
+----+------+
| id | a |
+----+------+
| 1 | 2 |
| 2 | 2 |
| 3 | 2 |
+----+------+
delete from t1 where id=2;
delete from t1 where id=3;
select * from t1;
+----+------+
| id | a |
+----+------+
| 1 | 2 |
+----+------+
insert into t1 values (null,2);我們看到插入了(2,2),而如果我沒有重啟,插入同樣資料我們得到的應該是(4,2)。 上面的測試反映了mysqld重啟後,innodb儲存引擎的表自增id可能出現重複利用的情況。select * from t1;
+----+------+
| id | a |
+----+------+
| 1 | 2 |
+----+------+
| 2 | 2 |
+----+------+
自增id重複利用在某些場景下會出現問題。依然用上面的例子,假設t1有個歷史表t1_history用來存t1表的歷史資料,那麼mysqld重啟前,ti_history中可能已經有了(2,2)這條資料,而重啟後我們又插入了(2,2),當新插入的(2,2)遷移到歷史表時,會違反主鍵約束。
原因分析
innodb 自增列出現重複值的原因
mysql> show create table t1\g;建表時可以指定 auto_increment值,不指定時預設為1,這個值表示當前自增列的起始值大小,如果新插入的資料沒有指定自增列的值,那麼自增列的值即為這個起始值。對於innodb表,這個值沒有持久到檔案中。而是存在記憶體中(dict_table_struct.autoinc)。那麼又問,既然這個值沒有持久下來,為什麼我們每次插入新的值後, show create table t1看到auto_increment值是跟隨變化的。其實show create table t1是直接從dict_table_struct.autoinc取得的(ha_innobase::update_create_info)。*************************** 1. row ***************************
table: t1
create table: create table `t1` (
`id` int(11) not null auto_increment,
`a` int(11) default null,
primary key (`id`)
) engine=innodb auto_increment=4 default charset=utf8
1 row in set (0.00 sec)
知道了auto_increment是實時儲存記憶體中的。那麼,mysqld 重啟後,從**得到auto_increment呢? 記憶體值肯定是丟失了。實際上mysql採用執行類似select max(id)+1 from t1;方法來得到auto_increment。而這種方法就是造成自增id重複的原因。
myisam自增值
myisam也有這個問題嗎?myisam是沒有這個問題的。myisam會將這個值實時儲存在.myi檔案中(mi_state_info_write)。mysqld重起後會從.myi中讀取auto_increment值(mi_state_info_read)。因此,myisam表重啟是不會出現自增id重複的問題。
問題修復
Sybase IQ自增列identify值的返回
sybase iq自增列identify值的返回 做專案的時候使用到了sybase iq資料庫,由於sybase沒有oracle的sequence概念,在處理插入併發時,一般只能使用到identify自增列,但是這個自增列的值如何獲取,還是需要了解一番的。一般使用如下方法獲取 sql set noc...
oracle自增列的問題
建立表 create table test id number primary key,name varchar2 not null 建立序列 create sequence test seq start with 1 increment by 1 建立觸發器 create or replace t...
mysql 自增列相關問題整理
mysql自增列 1.關鍵字 auto increment 2.自增用法 例 create table animals id mediumint not null auto increment,name char 30 not null,primary key id 3.關於自增 q 怎麼獲得當前的...