mysql的auto_increment詳解

gaopengtttt發表於2016-04-06

轉載http://blog.csdn.net/fwkjdaghappy1/article/details/7663331
  • auto_increment的基本特性


MySQL的中AUTO_INCREMENT型別的屬性用於為一個表中記錄自動生成ID功能,可在一定程度上代替Oracle,PostgreSQL等資料庫中的sequence。

在資料庫應用,我們經常要用到唯一編號,以標識記錄。在MySQL中可透過資料列的AUTO_INCREMENT屬性來自動生成。

可在建表時可用“AUTO_INCREMENT=n”選項來指定一個自增的初始值。
可用alter table table_name AUTO_INCREMENT=n命令來重設自增的起始值。

當插入記錄時,如果為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 plain copy
  1. delete from table_name;  
  2. 或者  
  3. truncate table table_name   
這是因為進行全表操作時,MySQL(和PHP搭配之最佳組合)實際是做了這樣的最佳化操作:先把資料表裡的所有資料和索引刪除,然後重建資料表。
如果想刪除所有的資料行又想保留序列編號資訊,可這樣用一個帶where的delete命令以抑制MySQL(和PHP搭配之最佳組合)的最佳化:


[php] view plain copy
  1. 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

一、innodb_autoinc_lock_mode = 0 (“traditional” lock mod,傳統模式)。
這種方式就和mysql5.1.22以前一樣,為了向後相容而保留了這種模式,如同前面介紹的一樣,這種方式的特點就是“表級鎖定”,併發性較差。
二、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。
三、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應該是夠用了。


最後說一句今天遇到這個問題,在LOCK_MODE為AUTO_INC,而且事物回滾非常的慢,不得已停止資料庫重新啟動
mysql> select * from innodb_locks;
+-------------+-------------+-----------+-----------+---------------+------------+------------+-----------+----------+-----------+
| lock_id     | lock_trx_id | lock_mode | lock_type | lock_table    | lock_index | lock_space | lock_page | lock_rec | lock_data |
+-------------+-------------+-----------+-----------+---------------+------------+------------+-----------+----------+-----------+
| 2954466:518 | 2954466     | AUTO_INC  | TABLE     | `test`.`kkkm` | NULL       |       NULL |      NULL |     NULL | NULL      |
| 2954465:518 | 2954465     | AUTO_INC  | TABLE     | `test`.`kkkm` | NULL       |       NULL |      NULL |     NULL | NULL      |
+-------------+-------------+-----------+-----------+---------------+------------+------------+-----------+----------+-----------+

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2076462/,如需轉載,請註明出處,否則將追究法律責任。

相關文章