<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      INNODB自增主鍵的一些問題

      背景:

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

      問題一:表鎖

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

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

      插入類型說明:

      INSERT-LIKE:指所有的插入語句,比如 INSERT、REPLACE、INSERT…SELECT、REPLACE…SELECT,LOAD DATA等
      Simple inserts:指在插入前就能確定插入行數的語句,包括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 自增長值的產生使用互斥量對內存中的計數器進行累加操作,對于bulk insert 則還是使用表鎖的方式進行。

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

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

      解決:

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

      問題二:自增主鍵不連續

      5.1.22后 默認:innodb_autoinc_lock_mode = 1
      直接通過分析語句,獲得要插入的數量,然后一次性分配足夠的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已經是不連續了。

      原因:

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

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

            所以會發現:插入只有1行時,你看不到這個現象,并不預申請。而當有N>1行時,則需要。多申請的數目為N-1,因此執行后的自增值為:1+N+(N-1)。測試中為10行,則:1+10+9 =20,和 16不一致?原因是:當插入8行的時候,表的AUTO_INCREMENT已經是16了,所以插入10行時,id已經在第8行時預留了,所以直接使用,自增值仍為16。所以當插入8行的時候,多申請了7個id,即:9,10,11,12,13,14,15。按照例子中的方法插入8~15行,表的AUTO_INCREMENT始終是16

      驗證:

      插入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)

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

      所以導致ID不連續的原因是因為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還是連續的。

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

      解決:

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

      結論:

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

      總結:

      通過上面2個問題的說明,自增主鍵會產生表鎖,從而引發問題;自增主鍵有業務意義,不連續的主鍵導致主從主鍵不一致到出現問題。對于simple inserts 的插入類型,上面的問題都不會出現。對于Bulk inserts的插入類型,會出現上述的問題。

      更多信息:

      http://dinglin.iteye.com/blog/1279536

      http://hi.baidu.com/thinkinginlamp/item/a0320c82233c6c2a100ef3d0

      http://dev.mysql.com/doc/refman/5.5/en/innodb-auto-increment-handling.html 

      http://blog.chinaunix.net/uid-9950859-id-181376.html

       

      posted @ 2013-11-20 17:38  jyzhou  閱讀(12643)  評論(4)    收藏  舉報
      主站蜘蛛池模板: 国产欧美日韩一区二区加勒比| 久久精品国产99久久六动漫| 欧美性猛交xxxx黑人猛交| 美女一区二区三区在线观看视频| 欧洲lv尺码大精品久久久| 国产91精品调教在线播放| 爱性久久久久久久久| 亚洲第一极品精品无码久久| 国产99久久亚洲综合精品西瓜tv| 国精品午夜福利视频| 视频| 好吊视频在线一区二区三区| 亚洲av成人无码精品电影在线| 国产女人和拘做受视频免费| 精品国产精品中文字幕| 永久免费av网站可以直接看的 | 精品熟女少妇av免费久久| 色欲久久人妻内射| 亚洲精品香蕉一区二区| 欧美人与动zozo在线播放| 97国产露脸精品国产麻豆| 亚洲国产色婷婷久久99精品91| 亚洲成av人片天堂网无码| 男人的天堂av一二三区| 亚洲av第一区二区三区| 天天摸天天碰天天添| 国产一区二区黄色在线观看| 香蕉亚洲欧洲在线一区| 国产主播精品福利午夜二区| 国产va免费精品观看精品| 国产福利片无码区在线观看| 国产精品一区中文字幕| 又爽又黄又无遮挡的视频| 国产情侣一区二区三区| 成人无码精品1区2区3区免费看| 久久一区二区三区黄色片| 历史| 亚洲熟妇色自偷自拍另类| 国产情侣一区二区三区| 国产四虎永久免费观看| 中文字幕乱码在线播放|