特性介紹 | MySQL 自增列詳解(1):自增列概念及使用


本文首發於 2019-12-09 19:37:10

1. 概念

自增列,即 AUTO_INCREMENT,可用於為新的記錄生成唯一標識。

要求:

  1. AUTO_INCREMENT 是數據列的一種屬性,只適用於整數類型數據列。
  2. AUTO_INCREMENT 數據列必須具備 NOT NULL 屬性。

2. 使用方法

2.1. 創建含自增列的表

-- 不指定 AUTO_INCREMENT 的值,則從1開始
mysql> create table t1(a int auto_increment primary key,b int);
Query OK, 0 rows affected (0.01 sec)

-- 手動指定 AUTO_INCREMENT 的值
mysql> create table t2(a int auto_increment primary key,b int) AUTO_INCREMENT=100;
Query OK, 0 rows affected (0.02 sec)

2.2. 插入數據

-- 不指定自增列
mysql> insert into t1(b) values(1),(2);
Query OK, 1 row affected (0.00 sec)

mysql> select * from t1;
+---+------+
| a | b    |
+---+------+
| 1 |    1 |
| 2 |    2 |
+---+------+
3 rows in set (0.00 sec)

-- 指定自增列
mysql> insert into t1(a,b) values(3,3);
Query OK, 1 row affected (0.00 sec)

2.3. 如何查看表的 AUTO_INCREMENT 漲到了多少?

mysql> show create table t1;
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                     |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t1    | CREATE TABLE `t1` (
  `a` int(11) NOT NULL AUTO_INCREMENT,
  `b` int(11) DEFAULT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

2.4. 插入數據時能否有空洞?

可以的,但要注意 AUTO_INCREMENT 的值一定比自增列當前最大的記錄值大

-- 創造空洞
mysql> insert into t1(a,b) values(5,5);
Query OK, 1 row affected (0.00 sec)

mysql> select * from t1;
+---+------+
| a | b    |
+---+------+
| 1 |    1 |
| 2 |    2 |
| 3 |    3 |
| 5 |    5 |
+---+------+
5 rows in set (0.00 sec)

mysql> show create table t1;
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                     |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t1    | CREATE TABLE `t1` (
  `a` int(11) NOT NULL AUTO_INCREMENT,
  `b` int(11) DEFAULT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

2.5. 能否插入重復記錄

既然自增列是唯一記錄,那么肯定不能插入重復記錄。

-- 嘗試插入重復記錄
mysql> insert into t1(a,b) values(5,5);
ERROR 1062 (23000): Duplicate entry '5' for key 'PRIMARY'

2.6. 怎么修改 AUTO_INCREMENT 的值?

注意:AUTO_INCREMENT 不能小於當前自增列記錄的最大值。

-- 嘗試將 AUTO_INCREMENT 設為10
mysql> alter table t1 AUTO_INCREMENT=10;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show create table t1;
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                      |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t1    | CREATE TABLE `t1` (
  `a` int(11) NOT NULL AUTO_INCREMENT,
  `b` int(11) DEFAULT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

-- 嘗試將 AUTO_INCREMENT 設為4
mysql> alter table t1 AUTO_INCREMENT=4;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0

-- 由於自增列最大記錄值是5,那么 AUTO_INCREMENT 不能小於5,因此該值為6
mysql> show create table t1;
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                     |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t1    | CREATE TABLE `t1` (
  `a` int(11) NOT NULL AUTO_INCREMENT,
  `b` int(11) DEFAULT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

3. 問題

3.1. 自增列是否有上限?

由上文可見,自增列會一直增加,那是否有上限呢?

上文中表 t1 的自增列是 int 類型,由下表(MySQL 5.7)可見取值范圍是 -2147483648 到 2147483647( -231 ~ 231 - 1 )。

Type Storage (Bytes) Minimum Value Signed Minimum Value Unsigned Maximum Value Signed Maximum Value Unsigned
TINYINT 1 -128 0 127 255
SMALLINT 2 -32768 0 32767 65535
MEDIUMINT 3 -8388608 0 8388607 16777215
INT 4 -2147483648 0 2147483647 4294967295
BIGINT 8 -263 0 263-1 264-1

驗證如下:

mysql> show create table t1;
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                              |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t1    | CREATE TABLE `t1` (
  `a` int(11) NOT NULL AUTO_INCREMENT,
  `b` int(11) DEFAULT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=2147483644 DEFAULT CHARSET=utf8 |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

mysql> insert into t1(b) values(0),(0),(0);
Query OK, 1 row affected (0.00 sec)

mysql> insert into t1(b) values(0);
ERROR 1062 (23000): Duplicate entry '2147483647' for key 'PRIMARY'
mysql> show create table t1;
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                              |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t1    | CREATE TABLE `t1` (
  `a` int(11) NOT NULL AUTO_INCREMENT,
  `b` int(11) DEFAULT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=2147483647 DEFAULT CHARSET=utf8 |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

這里需要補充說明下 int(11) 中的數字的含義:

MySQL中整數數據類型后面的(N)指定顯示寬度
顯示寬度不影響查詢出來的結果。
顯示寬度限制了小數點的位置(只要實際數字不超過顯示寬度,這種情況下,數字顯示為原樣)。
顯示寬度也是一個有用的工具,可以讓開發人員知道應該將值填充到哪個長度。

3.2. 如何避免自增列超過最大值?

可以采用無符號的 BIGINT 類型(也可根據業務產生自增列的速度采用合適的類型),能極大提升自增列的范圍。

mysql> create table t2(a bigint unsigned primary key auto_increment,b int);
Query OK, 0 rows affected (0.00 sec)

mysql> alter table t2 auto_increment=18446744073709551613;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show create table t2;
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                    |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t2    | CREATE TABLE `t2` (
  `a` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `b` int(11) DEFAULT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=18446744073709551613 DEFAULT CHARSET=utf8 |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

mysql> insert into t2(b) values(0);
Query OK, 1 row affected (0.00 sec)

mysql> insert into t2(b) values(0);
ERROR 1467 (HY000): Failed to read auto-increment value from storage engine
mysql>
mysql> select * from t2;
+----------------------+------+
| a                    | b    |
+----------------------+------+
| 18446744073709551613 |    0 |
+----------------------+------+
1 row in set (0.00 sec)

UNSIGNED BIGINT 類型的范圍究竟有多大呢?

假如每秒自增100萬次,想要消耗完需要 18446744073709551613/1000000/3600/24/365=584942年。

有的朋友會問如果自增列不是采用BIGINT類型,那么達到最大值后該表就無法寫入,此時該怎么辦呢?

一般達到最大值后再次插入數據會報錯ERROR 1467 (HY000): Failed to read auto-increment value from storage engine,可以通過alter table 將自增列的類型設為數值范圍更大的類型(比如BIGINT)。

4. 總結

  1. AUTO_INCREMENT 列必定唯一,且僅用於整型類型。
  2. AUTO_INCREMENT 列會持續增長,不會因 delete 自增列最大的記錄而變小。
  3. 當 AUTO_INCREMENT 列達到當前類型的最大值后將無法插入數據,會報錯ERROR 1467 (HY000): Failed to read auto-increment value from storage engine,此時將自增列改為 BIGINT 類型可解決問題。
  4. 為了避免自增列達到最大值,可將其設為BIGINT類型。
  5. 使用 alter table 修改 AUTO_INCREMENT 列時,其值會取自增列當前最大記錄值+1將要設置的值的最大值。
  6. 在MySQL 5.7 中,將列設置成 AUTO_INCREMENT 之后,必須將其設置成主鍵/或者是主鍵的一部分,否則會報錯ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key

歡迎關注我的微信公眾號【數據庫內核】:分享主流開源數據庫和存儲引擎相關技術。

MySQL數據庫技術
標題 網址
GitHub https://dbkernel.github.io
知乎 https://www.zhihu.com/people/dbkernel/posts
思否(SegmentFault) https://segmentfault.com/u/dbkernel
掘金 https://juejin.im/user/5e9d3ed251882538083fed1f/posts
開源中國(oschina) https://my.oschina.net/dbkernel
博客園(cnblogs) https://www.cnblogs.com/dbkernel


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM