Auto_increment Mysql AUTO_INCREMENT 1.Innodb表的自動增長列可以手工插入,但是插入的值如果是空或者0,則實際插入的將是自動增長後的值 2.可以通過alter table t1 auto_incremenrt=n 語句強制設置自動增長列的初始值,預設從1開始, ...
Auto_increment
Mysql AUTO_INCREMENT
1.Innodb表的自動增長列可以手工插入,但是插入的值如果是空或者0,則實際插入的將是自動增長後的值
mysql> create table t1(id int not null auto_increment primary key,name varchar(10));
Query OK, 0 rows affected (0.06 sec)
mysql> desc t1;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(10) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)
mysql> insert into t1 values(0,'fanboshi');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t1 values(null,'duyalan');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1;
+----+----------+
| id | name |
+----+----------+
| 1 | fanboshi |
| 2 | duyalan |
+----+----------+
2 rows in set (0.00 sec)
2.可以通過alter table t1 auto_incremenrt=n 語句強制設置自動增長列的初始值,預設從1開始,但是該強制的預設值是保留在記憶體中的,如果該值在使用之前資料庫重新啟動,那麼這個強制的預設值就會丟失,就需要資料庫啟動後重新設置
mysql> alter table t1 auto_increment=5;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> insert into t1 values(null,'handudu');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1;
+----+----------+
| id | name |
+----+----------+
| 1 | fanboshi |
| 2 | duyalan |
| 5 | handudu |
+----+----------+
3 rows in set (0.00 sec)
3.可以是用last_insert_id()查詢當前線程最後插入記錄使用的值。如果一次插入多條記錄,那麼返回的是第一條記錄使用的自動增長值。
mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 5 |
+------------------+
1 row in set (0.00 sec)
註意last_insert_id()是所有表auto_increment的最新插入值,
因此在併發的情況下,獲取某表的最新插入auto_increment可能出現錯誤
4.對於innodb表,自動增長列必須是索引,且必須是組合索引的第一列,且一個表只能有一個auto_increment屬性。
mysql> create table t2(id int not null auto_increment,name varchar(10));
ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key
非主鍵
mysql> create table t2(id int not null auto_increment,name varchar(10),index(id));
Query OK, 0 rows affected (0.09 sec)
mysql> mysql> show index from t2;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t2 | 1 | id | 1 | id | A | 0 | NULL | NULL | | BTREE | | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)
mysql> show index from t2;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t2 | 1 | id | 1 | id | A | 0 | NULL | NULL | | BTREE | | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)
不是主鍵,只是有索引
mysql> insert into t2 values(1,'fan');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t2 values(2,'fan');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t2;
+----+------+
| id | name |
+----+------+
| 1 | fan |
| 2 | fan |
+----+------+
2 rows in set (0.00 sec)
如果是組合索引,也必須是組合索引的第一列
mysql> create table t3(id1 int not null auto_increment,id2 int,name varchar(10),index(id2,id1));
ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key
但是對於MyISAM表,自動增長列可以使組合索引的其他列,這樣插入記錄後,自動增長列是按照組合索引的前面幾列進行排序後遞增的。
mysql> create table t3_myisam(id1 int not null auto_increment,id2 int,name varchar(10),index(id2,id1)) engine=myisam;
Query OK, 0 rows affected (0.04 sec)
mysql> insert into t3_myisam(id2,name) values(3,'fanboshi'),(1,'duyalan'),(1,'daduzi'),(2,'fan'),(5,'hehe'),(6,'keke');
Query OK, 6 rows affected (0.03 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> select * from t3_myisam;
+-----+------+----------+
| id1 | id2 | name |
+-----+------+----------+
| 1 | 3 | fanboshi |
| 1 | 1 | duyalan |
| 2 | 1 | daduzi |
| 1 | 2 | fan |
| 1 | 5 | hehe |
| 1 | 6 | keke |
+-----+------+----------+
6 rows in set (0.00 sec)
好像看不出啥規律
再插入一次
mysql> insert into t3_myisam(id2,name) values(3,'fanboshi'),(1,'duyalan'),(1,'daduzi'),(2,'fan'),(5,'hehe'),(6,'keke');
Query OK, 6 rows affected (0.00 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> select * from t3_myisam order by id2,id1;
+-----+------+----------+
| id1 | id2 | name |
+-----+------+----------+
| 1 | 1 | duyalan |
| 2 | 1 | daduzi |
| 3 | 1 | duyalan |
| 4 | 1 | daduzi |
| 1 | 2 | fan |
| 2 | 2 | fan |
| 1 | 3 | fanboshi |
| 2 | 3 | fanboshi |
| 1 | 5 | hehe |
| 2 | 5 | hehe |
| 1 | 6 | keke |
| 2 | 6 | keke |
+-----+------+----------+
12 rows in set (0.00 sec)
id2=1有四個,所以id1有1,2,3,4
id2=2有倆,id1=1,2
自動增長列id1作為組合索引的第二列,對該表插入一些記錄後,可以發現自動增長列是按照組合索引第一列id2進行排序後分組遞增的
5.MyISAM 及INNODB表,表中auto_increment最大值被刪除,將不會被重用。就是說會跳號
mysql> insert into t1(name) values('hehe');
Query OK, 1 row affected (0.02 sec)
mysql> select * from t1;
+----+----------+
| id | name |
+----+----------+
| 1 | fanboshi |
| 2 | duyalan |
| 5 | handudu |
| 6 | hehe |
+----+----------+
4 rows in set (0.00 sec)
mysql> delete from t1 where id=6;
Query OK, 1 row affected (0.08 sec)
mysql> insert into t1(name) values('keke');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1;
+----+----------+
| id | name |
+----+----------+
| 1 | fanboshi |
| 2 | duyalan |
| 5 | handudu |
| 7 | keke |
+----+----------+
4 rows in set (0.00 sec)
6.用"WHERE auto_col IS NULL"條件選擇出新插入的行,即在INSERT後馬上用:
SELECT * FROM t4 WHERE id IS NULL;
選擇出來的將是新插入的行,而非真正的滿足"id IS NULL"條件的行。
但你要是再執行一次上述查詢,則返回的又變成了真正的滿足"a IS NULL"條件的行,
由於a是主鍵,因此肯定會返回空集。這看上去很詭異是嗎,不過MySQL也不想這麼乾,為了支持 ODBC標準
不過可以將SQL_AUTO_IS_NULL設為0來禁止這一用法。
此方法獲取last_insert_id不推薦
mysql> insert into t1(name) values('new');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1 where id is null;
Empty set (0.00 sec)
mysql> show variables like 'sql_auto_is_null';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| sql_auto_is_null | OFF |
+------------------+-------+
1 row in set (0.00 sec)
mysql> set session sql_auto_is_null=on;
Query OK, 0 rows affected (0.02 sec)
mysql> show variables like 'sql_auto_is_null';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| sql_auto_is_null | ON |
+------------------+-------+
1 row in set (0.00 sec)
mysql> select * from t1 where id is null;
+----+------+
| id | name |
+----+------+
| 8 | new |
+----+------+
1 row in set (0.01 sec)
mysql> select * from t1 where id is null;
Empty set (0.00 sec)
7.AUTO_INCREMENT屬性也給複製帶來了麻煩。一般情況下複製AUTO_INCREMENT屬性能正確工作,但以下情況還是有問題:
- INSERT DELAYED ... VALUES(LAST_INSERT_ID())不能被正確複製
- 存儲過程插入的使用AUTO_INCREMENT屬性的記錄不能被正確複製
- 通過"ALTER TABLE"命令增加AUTO_INCREMENT屬性時在主從節點上產生的值可能是不一樣的,因為這個各行AUTO_INCREMENT屬性的值取決於物理上的存儲順序。
8.對於replication的master-master方式 為防止auto_increment欄位的重覆,可做如下設置
A伺服器的my.cnf設置如下:
auto_increment_offset = 1
auto_increment_increment = 2
這樣A的auto_increment欄位產生的數值是:1, 3, 5, 7, ...
B伺服器的my.cnf設置如下:
auto_increment_offset = 2
auto_increment_increment = 2
這樣B的auto_increment欄位產生的數值是:2, 4, 6, 8, ...
8.根據官方的說明:If the value of auto_increment_offset is greater than that of auto_increment_increment, the value of auto_increment_offset is ignored. (如果auto_increment_offset的值大於auto_increment_increment的值,則auto_increment_offset的值會被忽略)
mysql> show variables like 'auto_increment%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
+--------------------------+-------+
2 rows in set (0.00 sec)
mysql> set session auto_increment_offset=5;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like 'auto_increment%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 1 |
| auto_increment_offset | 5 |
+--------------------------+-------+
2 rows in set (0.00 sec)
mysql> create table t5 like t1;
Query OK, 0 rows affected (0.07 sec)
mysql> desc t5;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(10) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
mysql> insert into t5(name) values('fanboshi');
Query OK, 1 row affected (0.01 sec)
mysql> select * from t5;
+----+----------+
| id | name |
+----+----------+
| 1 | fanboshi |
+----+----------+
1 row in set (0.00 sec)
mysql> set session auto_increment_increment=5;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t5(name) values('duyalan');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t5(name) values('heheda');
Query OK, 1 row affected (0.02 sec)
mysql> select * from t5;
+----+----------+
| id | name |
+----+----------+
| 1 | fanboshi |
| 5 | duyalan |
| 10 | heheda |
+----+----------+
3 rows in set (0.00 sec)