http://dev.mysql.com/doc/refman/5.6/en/innodb-auto-increment-handling.html
AUTO_INCREMENT Handling in InnoDB
下面所使用的表
CREATE TABLE people (
person_id BIGINT NOT NULL AUTO_INCREMENT,
first_name VARCHAR(20),
last_name VARCHAR(20),
PRIMARY KEY (person_id)
);
Traditional InnoDB Auto-Increment Locking
the initialization of auto-increment counter
auto-increment counter的初始化據我的分析存在於三個節點:
-
數據庫服務器啓動後表的第一次插入前
-
通過show table status命令查詢表的狀態信息,如果auto-increment counter沒有初始化,就要在show table status之前初始化。
-
表新建後,要初始化auto-increment counter。
下面是mysql官方文檔的描述:http://dev.mysql.com/doc/refman/5.6/en/innodb-auto-increment-traditional.html
If you specify an AUTO_INCREMENT column for an InnoDB table, the table handle in the InnoDB data dictionary contains a special counter called the auto-increment counter that is used in assigning new values for the column. This counter is stored only in main memory, not on disk.
InnoDB uses the following algorithm to initialize the auto-increment counter for a table t that contains an AUTO_INCREMENT column named ai_col: After a server startup(在服務器啓動後,counter的值由於存在內存中,會消失), for the first insert into a table t(對於第一次插入), InnoDB executes the equivalent(等價的,等效的) of this statement:
SELECT MAX(ai_col) FROM t FOR UPDATE;
InnoDB increments the value retrieved(取回,恢復) by the statement and assigns it to the column and to the auto-increment counter for the table. By default, the value is incremented by one(默認的這個值會增加one). This default can be overridden by the auto_increment_increment configuration setting.
If the table is empty, InnoDB uses the value 1. This default can be overridden by the auto_increment_offset configuration setting.
If a SHOW TABLE STATUS statement examines(調查) the table t before the auto-increment counter is initialized, InnoDB initializes but does not increment the value and stores it for use by later inserts. This initialization uses a normal exclusive-locking read on the table and the lock lasts to the end of the transaction.
如下所示,通過truncate將一張表初始化,通過show table status可以看到Auto_increment爲1,這只是存儲到counter中以供下次插入使用的。這個初始化過程會加一個排它鎖把表鎖住,這個鎖會一直持續到事務結束。
mysql> truncate people;
Query OK, 0 rows affected (0.54 sec)
mysql> show table status from local_database like 'people'\G
*************************** 1. row ***************************
Name: people
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 0
Avg_row_length: 0
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: 1
Create_time: 2014-11-04 15:36:51
Update_time: NULL
Check_time: NULL
Collation: latin1_swedish_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
mysql> select max(person_id) from people;
+----------------+
| max(person_id) |
+----------------+
| NULL |
+----------------+
1 row in set (0.00 sec)
auto-increment counter
accessing the auto-increment counter
最重要的一個概念:table-level AUTO-INC lock,作用就是當執行一個insert語句時,這個鎖會把表鎖住,知道這個insert語句執行完成,然後表解鎖,而不是等到這個事務結束。
When accessing the auto-increment counter, InnoDB uses a special table-level AUTO-INC lock that it keeps to the end of the current SQL statement, not to the end of the transaction. The special lock release strategy was introduced to improve concurrency for inserts into a table containing an AUTO_INCREMENT column. Nevertheless(然而,儘管如此), two transactions cannot have the AUTO-INC lock on the same table simultaneously(同時,一起,一齊), which can have a performance(性能) impact(影響) if the AUTO-INC lock is held for a long time. That might be the case for a statement such as INSERT INTO t1 ... SELECT ... FROM t2 that inserts all rows from one table into another.
auto_increment_increment&&auto_increment_offset
auto_increment_increment:自增值的自增量
auto_increment_offset: 自增值的偏移量
設置了兩個值之後,改服務器的自增字段值限定爲:
auto_increment_offset + auto_increment_increment*N 的值,其中N>=0,但是上限還是要受定義字段的類型限制。
比如:
auto_increment_offset=1
auto_increment_increment=2
那麼ID則是所有的奇數[1,3,5,7,.....]
如果:
auto_increment_offset=5
auto_increment_increment=10
那麼ID則是所有的奇數[5,15,25,35,.....]