Mysql中INNODB自增主鍵的問題有哪些

小編給大家分享一下MySQL中INNODB自增主鍵的問題有哪些,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

10年積累的網(wǎng)站制作、網(wǎng)站建設經(jīng)驗,可以快速應對客戶對網(wǎng)站的新想法和需求。提供各種問題對應的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡服務。我雖然不認識你,你也不認識我。但先網(wǎng)站設計后付款的網(wǎng)站建設流程,更有明溪免費網(wǎng)站建設讓你可以放心的選擇與我們合作。

背景:

      自增長是一個很常見的數(shù)據(jù)屬性,在MySQL中大家都很愿意讓自增長屬性的字段當一個主鍵。特別是InnoDB,因為InnoDB的聚集索引的特性,使用自增長屬性的字段當主鍵性能更好,這里要說明下自增主鍵需要注意的幾個事項。

問題一:表鎖

      在MySQL5.1.22之前,InnoDB自增值是通過其本身的自增長計數(shù)器來獲取值,該實現(xiàn)方式是通過表鎖機制來完成的(AUTO-INC LOCKING)。鎖不是在每次事務完成后釋放,而是在完成對自增長值插入的SQL語句后釋放,要等待其釋放才能進行后續(xù)操作。比如說當表里有一個auto_increment字段的時候,innoDB會在內存里保存一個計數(shù)器用來記錄auto_increment的值,當插入一個新行數(shù)據(jù)時,就會用一個表鎖來鎖住這個計數(shù)器,直到插入結束。如果大量的并發(fā)插入,表鎖會引起SQL堵塞。insert into.....select大量插入數(shù)據(jù)的性能也比較差

      在5.1.22之后,InnoDB為了解決自增主鍵鎖表的問題,引入了參數(shù)innodb_autoinc_lock_mode,該實現(xiàn)方式是通過輕量級互斥量的增長機制完成的。它是專門用來在使用auto_increment的情況下調整鎖策略的,目前有三種選擇:

插入類型說明:

INSERT-LIKE:指所有的插入語句,比如 INSERT、REPLACE、INSERT…SELECT、REPLACE…SELECT,LOAD DATA等
Simple inserts:指在插入前就能確定插入行數(shù)的語句,包括INSERT、REPLACE,不包含INSERT…ON DUPLICATE KEY UPDATE這類語句。
Bulk inserts:指在插入前不能確定得到插入行的語句。如INSERT…SELECT,REPLACE…SELECT,LOAD DATA.
Mixed-mode inserts:指其中一部分是自增長的,有一部分是確定的。

0:通過表鎖的方式進行,也就是所有類型的insert都用AUTO-inc locking。

1:默認值,對于simple insert 自增長值的產生使用互斥量對內存中的計數(shù)器進行累加操作,對于bulk insert 則還是使用表鎖的方式進行。

2:對所有的insert-like 自增長值的產生使用互斥量機制完成,性能最高,并發(fā)插入可能導致自增值不連續(xù),可能會導致Statement 的 Replication 出現(xiàn)不一致,使用該模式,需要用 Row Replication的模式。

      在mysql5.1.22之前,mysql的INSERT-LIKE語句會在執(zhí)行整個語句的過程中使用一個AUTO-INC鎖將表鎖住,直到整個語句結束(而不是事務結束)。因此在使用INSERT…SELECT、INSERT…values(…),values(…)時,LOAD DATA等耗費時間較長的操作時,會將整個表鎖住,而阻塞其他的insert-like,update等語句。推薦使用程序將這些語句分成多條語句,一一插入,減少單一時間的鎖表時間。

解決:

通過參數(shù)innodb_autoinc_lock_mode =1/2解決,并用simple inserts 模式插入。

問題二:自增主鍵不連續(xù)

5.1.22后 默認:innodb_autoinc_lock_mode = 1
直接通過分析語句,獲得要插入的數(shù)量,然后一次性分配足夠的auto_increment id,只會將整個分配的過程鎖住。

root@localhost : test 04:23:28>show variables like 'innodb_autoinc_lock_mode'; +--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | innodb_autoinc_lock_mode | 1 | +--------------------------+-------+ 1 row in set (0.00 sec)

root@localhost : test 04:23:31>create table tmp_auto_inc(id int auto_increment primary key,talkid int)engine = innodb default charset gbk;
Query OK, 0 rows affected (0.16 sec)

root@localhost : test 04:23:35>insert into tmp_auto_inc(talkid) select talkId from talk_dialog limit 10;
Query OK, 10 rows affected (0.00 sec)
Records: 10 Duplicates: 0 Warnings: 0 root@localhost : test 04:23:39>show create table tmp_auto_inc\G; *************************** 1. row *************************** Table: tmp_auto_inc Create Table: CREATE TABLE `tmp_auto_inc` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `talkid` int(11) DEFAULT NULL, PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=gbk 1 row in set (0.00 sec)

插入10條記錄,但表的AUTO_INCREMENT=16,再插入一條的時候,表的自增id已經(jīng)是不連續(xù)了。

原因:

      參數(shù)innodb_autoinc_lock_mode = 1時,每次會“預申請”多余的id(handler.cc:compute_next_insert_id),而insert執(zhí)行完成后,會特別將這些預留的id空出,就是特意將預申請后的當前最大id回寫到表中(dict0dict.c:dict_table_autoinc_update_if_greater)。

      這個預留的策略是“不夠時多申請幾個”, 實際執(zhí)行中是分步申請。至于申請幾個,是由當時“已經(jīng)插入了幾條數(shù)據(jù)N”決定的。當auto_increment_offset=1時,預申請的個數(shù)是 N-1。

      所以會發(fā)現(xiàn):插入只有1行時,你看不到這個現(xiàn)象,并不預申請。而當有N>1行時,則需要。多申請的數(shù)目為N-1,因此執(zhí)行后的自增值為:1+N+(N-1)。測試中為10行,則:1+10+9 =20,和 16不一致?原因是:當插入8行的時候,表的AUTO_INCREMENT已經(jīng)是16了,所以插入10行時,id已經(jīng)在第8行時預留了,所以直接使用,自增值仍為16。所以當插入8行的時候,多申請了7個id,即:9,10,11,12,13,14,15。按照例子中的方法插入8~15行,表的AUTO_INCREMENT始終是16
為了發(fā)現(xiàn)規(guī)律,這兒我做了實驗,不是很準確,插入行數(shù)與對應的autocommit分別是 2》4   3》4   4-7》8  8-15》16 16-31》32),只能說AUTO_INCREMENT有可能是2n(具體什么時候是2n還沒發(fā)現(xiàn)規(guī)律),范圍應該是[n,2n]之間

驗證:

插入16行:猜測 預申請的id:1+16+(16-1)= 32,即:AUTO_INCREMENT=32

root@localhost : test 04:55:45>create table tmp_auto_inc(id int auto_increment primary key,talkid int)engine = innodb default charset gbk;
Query OK, 0 rows affected (0.17 sec)

root@localhost : test 04:55:48>insert into tmp_auto_inc(talkid) select talkId from sns_talk_dialog limit 16;
Query OK, 16 rows affected (0.00 sec)
Records: 16 Duplicates: 0 Warnings: 0 root@localhost :
test 04:55:50>show create table tmp_auto_inc\G;
*************************** 1. row ***************************
Table: tmp_auto_inc Create Table: CREATE TABLE `tmp_auto_inc` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `talkid` int(11) DEFAULT NULL, PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=gbk 1 row in set (0.00 sec)               ---第一次插入所以為2*16



和猜測的一樣,自增id到了32。所以當插入16行的時候,多申請了17,18,19...,31 。

所以導致ID不連續(xù)的原因是因為innodb_autoinc_lock_mode = 1時,會多申請id。好處是:一次性分配足夠的auto_increment id,只會將整個分配的過程鎖住。

5.1.22前 默認:innodb_autoinc_lock_mode = 0

root@localhost : test 04:25:12>show variables like 'innodb_autoinc_lock_mode';
+--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | innodb_autoinc_lock_mode | 0 | +--------------------------+-------+
1 row in set (0.00 sec)

root@localhost : test 04:25:15>create table tmp_auto_inc(id int auto_increment primary key,talkid int)engine = innodb default charset gbk;
Query OK, 0 rows affected (0.17 sec)

root@localhost : test 04:25:17>insert into tmp_auto_inc(talkid) select talkId from talk_dialog limit 10;
Query OK, 10 rows affected (0.00 sec)
Records: 10 Duplicates: 0 Warnings: 0
root@localhost : test 04:25:21>show create table tmp_auto_inc\G;
*************************** 1. row ***************************
Table: tmp_auto_inc Create Table: CREATE TABLE `tmp_auto_inc` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `talkid` int(11) DEFAULT NULL, PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=gbk 1 row in set (0.00 sec)

插入10條記錄,但表的AUTO_INCREMENT=11,再插入一條的時候,表的自增id還是連續(xù)的。

innodb_autoinc_lock_mode = 2 和 innodb_autoinc_lock_mode = 1 的測試情況一樣。但該模式下是來一個分配一個,而不會鎖表,只會鎖住分配id的過程,和1的區(qū)別在于,不會預分配多個,這種方式并發(fā)性最高。但是在replication中當binlog_format為statement-based時存在問題

解決:

盡量讓主鍵ID沒有業(yè)務意義,或則使用simple inserts模式插入。

結論:

當innodb_autoinc_lock_mode為0時候, 自增id都會連續(xù),但是會出現(xiàn)表鎖的情況,解決該問題可以把innodb_autoinc_lock_mode 設置為1,甚至是2。會提高性能,但是會在一定的條件下導致自增id不連續(xù)。

以上是“Mysql中INNODB自增主鍵的問題有哪些”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

本文題目:Mysql中INNODB自增主鍵的問題有哪些
本文來源:http://bm7419.com/article12/goeogc.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站收錄、營銷型網(wǎng)站建設、定制網(wǎng)站面包屑導航、自適應網(wǎng)站微信公眾號

廣告

聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

外貿網(wǎng)站制作