MySQL的中AUTO_INCREMENT類型的屬性用於爲一個表中記錄自動生成ID功能,可在必定程度上代替Oracle,PostgreSQL等數據庫中的sequence。php
在數據庫應用,咱們常常要用到惟一編號,以標識記錄。在MySQL中可經過數據列的AUTO_INCREMENT屬性來自動生成。mysql
可在建表時可用「AUTO_INCREMENT=n」選項來指定一個自增的初始值。
可用alter table table_name AUTO_INCREMENT=n命令來重設自增的起始值。
sql
當插入記錄時,若是爲AUTO_INCREMENT數據列明確指定了一個數值,則會出現兩種狀況,
狀況一,若是插入的值與已有的編號重複,則會出現出錯信息,由於AUTO_INCREMENT數據列的值必須是惟一的;
狀況二,若是插入的值大於已編號的值,則會把該插入到數據列中,並使在下一個編號將從這個新值開始遞增。也就是說,能夠跳過一些編號。
若是自增序列的最大值被刪除了,則在插入新記錄時,該值被重用。
若是用UPDATE命令更新自增列,若是列值與已有的值重複,則會出錯。若是大於已有值,則下一個編號從該值開始遞增。數據庫
在使用AUTO_INCREMENT時,應注意如下幾點:
AUTO_INCREMENT是數據列的一種屬性,只適用於整數類型數據列。
設置AUTO_INCREMENT屬性的數據列應該是一個正數序列,因此應該把該數據列聲明爲UNSIGNED,這樣序列的編號個可增長一倍。
AUTO_INCREMENT數據列必須有惟一索引,以免序號重複(便是主鍵或者主鍵的一部分)。
AUTO_INCREMENT數據列必須具有NOT NULL屬性。
AUTO_INCREMENT數據列序號的最大值受該列的數據類型約束,如TINYINT數據列的最大編號是127,如加上UNSIGNED,則最大爲255。一旦達到上限,AUTO_INCREMENT就會失效。
當進行全表刪除時,MySQL AUTO_INCREMENT會從1從新開始編號。全表刪除的意思是發出如下兩條語句時:
併發
[php] view plaincopyapp
delete from table_name; 測試
或者 優化
truncate table table_name spa
這是由於進行全表操做時,MySQL(和PHP搭配之最佳組合)實際是作了這樣的優化操做:先把數據表裏的全部數據和索引刪除,而後重建數據表。
若是想刪除全部的數據行又想保留序列編號信息,可這樣用一個帶where的delete命令以抑制MySQL(和PHP搭配之最佳組合)的優化:.net
[php] view plaincopy
delete from table_name where 1;
可用last_insert_id()獲取剛剛自增過的值。
關於mysql auto_increment所帶來的鎖表操做
在 mysql5.1.22以前,mysql的「INSERT-like」語句(包INSERT, INSERT…SELECT, REPLACE,REPLACE…SELECT, and LOAD DATA)會在執行整個語句的過程當中使用一個AUTO-INC鎖將表鎖住,直到整個語句結束(而不是事務結束)。
所以在使用INSERT…SELECT、 INSERT…values(…),values(…)時,LOAD DATA等耗費時間較長的操做時,會將整個表鎖住,而阻塞其餘的「INSERT-like」、Update等語句,推薦使用程序將這些語句分紅多條語句, 一一插入,減小單一時間的鎖表時間。
mysql5.1.22以後mysql進行了改進,引入了參數 innodb_autoinc_lock_mode,經過這個參數控制mysql的鎖表邏輯。
在介紹這個以前先引入幾個術語,方便說明 innodb_autoinc_lock_mode。
1.「INSERT-like」:
INSERT, INSERT … SELECT, REPLACE, REPLACE … SELECT, and LOAD DATA, INSERT … VALUES(),VALUES()
2.「Simple inserts」:
就是經過分析insert語句能夠肯定插入數量的insert語句, INSERT, INSERT … VALUES(),VALUES()
3.「Bulk inserts」:
就是經過分析insert語句不能肯定插入數量的insert語句, INSERT … SELECT, REPLACE … SELECT, LOAD DATA
4.「Mixed-mode inserts」:
不肯定是否須要分配auto_increment id,通常是下面兩種狀況
INSERT INTO t1 (c1,c2) VALUES (1,’a'), (NULL,’b'), (5,’c'), (NULL,’d');
INSERT … ON DUPLICATE KEY UPDATE
1、innodb_autoinc_lock_mode = 0 (「traditional」 lock mod,傳統模式)。
這種方式就和mysql5.1.22之前同樣,爲了向後兼容而保留了這種模式,如同前面介紹的同樣,這種方式的特色就是「表級鎖定」,併發性較差。
2、innodb_autoinc_lock_mode = 1 (「consecutive」 lock mode,連續模式)。
這種方式是新版本中的默認方式,推薦使用,併發性相對較高,特色是「consecutive」,即保證同一條insert語句中新插入的auto_increment id都是連續的。
這種模式下:
「Simple inserts」:直接經過分析語句,得到要插入的數量,而後一次性分配足夠的auto_increment id,只會將整個分配的過程鎖住。
「Bulk inserts」:由於不能肯定插入的數量,所以使用和之前的模式相同的表級鎖定。
「Mixed-mode inserts」:直接分析語句,得到最壞狀況下須要插入的數量,而後一次性分配足夠的auto_increment id,只會將整個分配的過程鎖住。
須要注意的是,這種方式下,會分配過多的id,而致使「浪費」。
好比INSERT INTO t1 (c1,c2) VALUES (1,’a'), (NULL,’b'), (5,’c'), (NULL,’d');會一次性的分配5個id,而無論用戶是否指定了部分id;
INSERT … ON DUPLICATE KEY UPDATE一次性分配,而無論未來插入過程當中是否會由於duplicate key而僅僅執行update操做。
注意:當master mysql版本<5.1.22,slave mysql版本>=5.1.22時,slave須要將innodb_autoinc_lock_mode設置爲0,由於默認的 innodb_autoinc_lock_mode爲1,對於INSERT … ON DUPLICATE KEY UPDATE和INSERT INTO t1 (c1,c2) VALUES (1,’a'), (NULL,’b'), (5,’c'), (NULL,’d');的執行結果不一樣,現實環境通常會使用INSERT … ON DUPLICATE KEY UPDATE。
3、innodb_autoinc_lock_mode = 2 (「interleaved」 lock mode,交叉模式)。
這種模式是來一個分配一個,而不會鎖表,只會鎖住分配id的過程,和innodb_autoinc_lock_mode = 1的區別在於,不會預分配多個,這種方式併發性最高。
可是在replication中當binlog_format爲statement- based時(簡稱SBR statement-based replication)存在問題,由於是來一個分配一個,這樣當併發執行時,「Bulk inserts」在分配的時會同時向其餘的INSERT分配,會出現主從不一致(從庫執行結果和主庫執行結果不同),由於binlog只會記錄開始的 insert id。
測試SBR,執行begin;insert values(),();insert values(),();commit;會在binlog中每條insert values(),();前增長SET INSERT_ID=18/*!*/;。
可是row-based replication RBR時不會存在問題。
另外RBR的主要缺點是日誌數量在包括語句中包含大量的update delete(update多條語句,delete多條語句)時,日誌會比SBR大不少;假如實際語句中這樣語句不是不少的時候(現實中存在不少這樣的情 況),推薦使用RBR配合innodb_autoinc_lock_mode,不過話說回來,現實生產中「Bulk inserts」原本就不多,所以innodb_autoinc_lock_mode = 1應該是夠用了。