MySQL 中 AUTO_INCREMENT 的“坑”--id不连续
背景
最近在玩 MySQL 雙主復制架構,表里的主鍵使用自增ID,為了避免兩臺主庫生成的主鍵沖突,遂兩臺主庫分別配置如下:
server 1 的 my.cnf :
server 2 的 my.cnf :
auto_increment_increment = 2 auto_increment_offset = 2按照這個配置,本以為 server 1 和 server 2 生成序列分別是 1 ,3 ,5 ··· 和 2 , 4, 6 ··· 這樣的序列,但事實上并不完全是這樣,下面來做個試驗。
問題重現
基于以上配置,在 server 1 上建表:
CREATE TABLE `test`.`table_name` (`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,`name` VARCHAR(50) NULL,PRIMARY KEY (`id`)) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8mb4;因為我配置了雙主同步,所以此表將被同步到 server 2 上。
執行如下添加語句初始化數據:
INSERT INTO `test`.`table_name` (`name`) VALUES ('myname0'); INSERT INTO `test`.`table_name` (`name`) VALUES ('myname1'); INSERT INTO `test`.`table_name` (`name`) VALUES ('myname2');數據將被同步到 server 2 上。
在 server 1 上查詢此表,可以看到剛才插入的數據:
| 1 | myname0 |
| 3 | myname1 |
| 5 | myname2 |
結果如我們所料,id 列呈奇數自增。在 server 2 上查詢的結果和上面一樣。
接著,在 server 2 上向此表再添加幾條數據:
INSERT INTO `test`.`table_name` (`name`) VALUES ('myname3'); INSERT INTO `test`.`table_name` (`name`) VALUES ('myname4'); INSERT INTO `test`.`table_name` (`name`) VALUES ('myname5');同樣數據,將被同步到 server 1 上。
查詢此表,得到的結果:
| 1 | myname0 |
| 3 | myname1 |
| 5 | myname2 |
| 6 | myname3 |
| 8 | myname4 |
| 10 | myname5 |
問題出來了,server 2 分配的序列并不像我們之前期望的那樣,從 2 開始的連續偶數,而是跳過 2 和 4,直接從 6 開始。
解決
研究了很久,翻看 MySQL 官網文檔,都說,自增ID分別是 1、2、3 和 2 、 4 、 6 ,并沒有對此情況做明確說明。
直到我看到 這位大神的回答。其實id的計算: INT(current_value / increment) x increment + offset.
總結
總結一下:
1. AUTO_INCREMENT 所在的列,必須為整數型數據列
2. AUTO_INCREMENT 所在的列,不能為空
3. AUTO_INCREMENT 所在的列,必須有唯一索引
4. AUTO_INCREMENT 所在的列,值必須大于0
5. AUTO_INCREMENT 所在的列,最大值,受其數據類型及是否為 無符號(Unsigned) 限制,若使用的為 TINYINT(4) 且 為無符號的,則最大值為 255,若繼續插入數據,則該列的值保持最大值不變,
6. AUTO_INCREMENT 所在的列,若向其中插入的值,大于所在表當前的 AUTO_INCREMENT 值,則會更新表 AUTO_INCREMENT 值至 current_max_value - (current_max_value - auto_increment_offset) % auto_increment_increment + auto_increment_increment ,即該列的下一個序列值
總結
以上是生活随笔為你收集整理的MySQL 中 AUTO_INCREMENT 的“坑”--id不连续的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring boo系列--jpa和th
- 下一篇: MySQL 中 AUTO_INCREME