中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

InnoDB中的row_id與自增鍵用完怎么辦

發布時間:2020-06-10 15:31:10 來源:億速云 閱讀:416 作者:元一 欄目:編程語言

在數據庫表設計中會糾結于”自然鍵”和”代理鍵”的選擇,自然鍵在實現數據“軟刪除”時實現比較復雜,部分自然鍵因為鍵值過長或多列組合導致不適合作為表主鍵,而比較常見兩種代理鍵為自增列(auto incremnet)和全局唯一標識列(GUID)。

使用自增列作為主鍵的優缺點:

1、 主鍵鍵值長度短,INT列需要4個字節,BIGINT列需要8個字節;

2、 自增主鍵順序遞增,在INSERT操作時”順序”寫入表;

3、 由于數據集中插入到表尾部,在高并發情況下容易造成”數據頁熱點”,影響插入效率;

4、 自增主鍵只能保證在表內數據唯一,對于分庫分表場景,可能因錯誤操作產生相同的“唯一值”。

自增鍵用完了會發生什么?

我們在建表的時候為某個索引列( 注意:必須是索引列 )添加 AUTO_INCREMENT 屬性,就像這樣:

CREATE TABLE t (    c1 TINYINT AUTO_INCREMENT,    c2 TINYINT,    KEY idx_c1 (c1)) ENGINE=InnoDB;

表 t 中包含一個索引列 c1 ,該列被添加了 AUTO_INCREMENT 屬性。我們先向該表中插入一條記錄:

mysql> INSERT INTO t(c1, c2) VALUES(126, 1);Query OK, 1 row affected (0.02 sec)

之后我們不再在 INSERT 語句中顯式地插入 c1 列的值,它的默認值就將是從當前插入的最大的那個值之后自增,比如這樣:

mysql> INSERT INTO t(c2) VALUES(1);Query OK, 1 row affected (0.01 sec)

我們看一下此時表 t 中的數據:

mysql> SELECT * FROM t;+-----+------+| c1  | c2   |+-----+------+| 126 |    1 || 127 |    1 |+-----+------+2 rows in set (0.02 sec)

因為 c1 列是 TINYINT 類型的,使用1個字節存儲數據,它能存儲最大的值就是 127 ,如果當該列的值到達 127 之后,我們繼續向表中插入數據,自增列 c1 的值將會變成什么呢?

mysql> INSERT INTO t(c2) VALUES(1);Query OK, 1 row affected (0.01 sec)

插入成功之后我們再看一下表中的數據:

mysql> SELECT * FROM t;+-----+------+| c1  | c2   |+-----+------+| 126 |    1 || 127 |    1 || 127 |    1 |+-----+------+3 rows in set (0.01 sec)

很顯然,自增列 c1 的值將不再繼續增長,而是取的 TINYINT 所能存儲的最大值。

這里需要注意的是,在當前舉的例子中,我們只是在自增列 c1 上邊建立了一個普通的二級索引 idx_c1 ,所以鍵值重復也沒啥問題。不過我們一般將 AUTO_INCREMENT 屬性應用在表的主鍵上,此時如果自增列值達到了主鍵對應數據類型所能存儲的最大值時,就會報錯(因為主鍵值重復),大家一定注意!

row_id用完了會發生什么?
在我們使用 InnoDB 存儲引擎來建表時,如果我們自己沒有顯式地創建主鍵時,存儲引擎會默認找一個具有 NOT NULL 屬性的唯一二級索引列來充當主鍵,如果我們在建表語句中也沒有寫具有 NOT NULL 屬性的唯一二級索引列,那很抱歉,存儲引擎默認會為我們添加一個稱之為 row_id 的主鍵列。

這個 row_id 列默認是6個字節大小,值得注意的是,設計 InnoDB 的大叔并不是為每一個用戶未顯式創建主鍵的表的 row_id 列都單獨維護一個計數器,而是所有的表都共享一個全局的計數器。比方說我們沒有對表 t1 和 t2 顯式創建主鍵,存儲引擎為它們都創建了一個 row_id 列,如果我們向表 t1 中插入了一條記錄,那么就從全局計數器里分配一個值做該表 row_id 列的值,然后將全局計數器加1;接著我們再向表 t2 中插入一條記錄,那么就再從全局計數器里分配一個值做該表 row_id 列的值,然后將全局計數器加1。

有很多同學有疑惑,如果這個全局計數器的值超過了6個字節所能表示的最大值時,會發生什么,全局計數器從0重新開始技術,一切從頭再來么?

哈哈:smile:,并不會這樣。雖然 row_id 由6個字節組成,但是設計 InnoDB 的大叔卻是使用8個字節存儲全局計數器的值,他們將這8個字節分兩次寫入 row_id ,第一次寫入右邊四個字節到 row_id 的右邊4個字節,接著將左邊四個字節再寫入 row_id 的左邊的2個字節,就像這樣:
InnoDB中的row_id與自增鍵用完怎么辦

在將全局計數器左邊四個字節再寫入 row_id 的左邊的2個字節 時采用如下函數:

UNIV_INLINEvoidmach_write_to_2(/*============*/byte*b,/*!< in: pointer to two bytes where to store 也就是row_id值前2個字節所在的內存地址*/ulintn)/*!< in: ulint integer to be stored 也就是全局計數器的左4個字節值*/{ut_ad(b);ut_ad((n | 0xFFFFUL) <= 0xFFFFUL);b[0] = (byte)(n >> 8);b[1] = (byte)(n);}

可以看到代碼中有這樣一行:

ut_ad((n | 0xFFFFUL) <= 0xFFFFUL);

這是一個斷言函數,這行代碼的意思就是全局計數器的左邊4個字節值 n 必須不大于2個字節所能存儲的最大值,否則的話斷言就失敗了,然后MySQL就掛掉了,就掛掉了,就掛掉了~

也就是說如果 row_id 用完了之后MySQL就會掛掉,那種程序直接退出的掛掉~ 不過6個字節已經足夠大了,大家可以算算如果想讓MySQL掛掉需要插入多少條記錄呢?

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

汉阴县| 西城区| 甘孜县| 宝丰县| 奎屯市| 民权县| 永城市| 青海省| 苍梧县| 临高县| 镇远县| 南通市| 高邑县| 葵青区| 湖北省| 台北市| 炉霍县| 通化县| 小金县| 化德县| 天等县| 吉木萨尔县| 淳安县| 阿克苏市| 五大连池市| 彰武县| 青州市| 马山县| 石景山区| 东安县| 康定县| 荣成市| 黑河市| 马鞍山市| 许昌市| 桐庐县| 梅河口市| 浪卡子县| 石首市| 泉州市| 梁河县|