前情提要:
最近新接了一個需求,需要去創建兩張表,其中有一張表需要根據業務id和業務類型建立唯一索引,對數據唯一性進行約束。
因為涉及到業務嘛,表結構就進行縮略了
表結構示例如下: CREATE TABLE `example_table` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主鍵', `business_id` bigint(20) unsigned NOT NULL COMMENT '業務ID', `business_type` tinyint(3) unsigned NOT NULL COMMENT '業務類型,', `del` tinyint(1) unsigned DEFAULT '0' COMMENT '刪除標識,0表示未刪除,1表示刪除', `creator` varchar(50) NOT NULL COMMENT '創建人PIN', `modify_date` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間', `create_date` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間', PRIMARY KEY (`id`), UNIQUE KEY `uk_business_id_and_type` (`business_id`,`business_type`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COMMENT='示例表'
既然表建立好,那么就是發揮我們編碼能力的時候了...此處省略一堆編碼時間。
編碼結束,自測結束,信心滿滿的找前端同學進行聯調。
因為聯調嘛,mock了很多同樣的business_id和bussiness_type的數據,結果到了數據庫,因為唯一索引的約束,報了一堆錯誤,插入都失敗了。
終于調整了一下mock數據,插入成功了。
但是發生了一個比較神奇的現象
主鍵不是連續自增的了~~ 中間丟失的自增主鍵去哪了??
關于自增主鍵
自增主鍵是我們在設計數據庫表結構時經常使用的主鍵生成策略,主鍵的生成可以完全依賴數據庫,在新增數據的時候,我們只需要將主鍵設置為null,0或者不設置該字段,數據庫就會為我們自動生成一個主鍵值。
首先,我們要知道 自增主鍵保存在哪里~
不同的引擎對于自增值的保存策略不同
1.MyISAM引擎的自增值保存在數據文件中
2.InnoDB引擎的自增值,在MySQL5.7及之前的版本,自增值保存在內存里,并沒有持久化。每次重啟后,第一次打開表的時候,都會去找自增值的最大值max(id),然后將max(id)+步長(建表語句中的指定步長)作為這個表當前的自增值。在MySQL8.0版本,將自增值的變更記錄在了redo log中,重啟的時候依靠redo log恢復重啟之前的值。
了解了自增主鍵的保存機制,再了解一下主鍵這個"自增"邏輯~
插入一條語句分配自增主鍵id值的流程如圖所示。
自增主鍵不連續的情況
細心的小伙伴一定發現了~咦,這個ID=聲明值的話,ID就可以能被隨意指定了,那么ID就可能存在不是自增的情況了!
是的,這其實就是第一種自增主鍵不連續的情況。
第二種不連續的情況就是我們在聯調中遇到的問題了
簡單來做個測試,目前數據就像一開始的圖一樣,id自增到了24,下一個插入的應該是25,那么執行一條sql
insert into example_table values (null,111,1,0,'mock',now(),now());
插入成功了一條數據,主鍵是連續自增的。
那么我們模擬一條錯誤的sql呢(`creator`字段指定錯類型)~:
insert into example_table values (null,112,1,0,mock,now(),now());
果然,執行sql 的時候報出異常:
繼續執行一條正確的正常的sql,插入結果:
主鍵還是連續自增的。這個發生錯誤為什么自增主鍵還是連續的呢。我們模擬一下之前聯調遇到的情況,插入一條 sql:
insert into example_table values (null,112,1,0,'mock',now(),now());
因為id=26的數據buiness_id和bussiness_type 跟新插入的這條數據一樣,那么肯定會因為唯一索引插入不成功,果然,執行結果如下:
那么,我們修改一下sql繼續插入呢?
insert into example_table values (null,113,1,0,'mock',now(),now())
主鍵發生了"斷代",27的主鍵跑丟了...
明明都是sql插入的時候錯誤,為什么結果會有差異呢,有的時候主鍵會丟失,有的時候主鍵不會丟失呢,想要弄明白這個問題,就需要先明白一下一條sql的執行過程:
這里只是針對本文需要關注的點(相信小伙伴對這個執行過程肯定也是非常了解的
審核編輯 黃宇
-
開發
+關注
關注
0文章
367瀏覽量
40811 -
SQL
+關注
關注
1文章
760瀏覽量
44080 -
編碼
+關注
關注
6文章
935瀏覽量
54771
發布評論請先 登錄
相關推薦
評論