MySQL auto_increment的坑

來源:互聯網
上載者:User

標籤:

 

背景:

  Innodb引擎使用B_tree結構儲存表資料,這樣就需要一個唯一鍵表示每一行記錄(比如二級索引記錄引用)。

  Innodb表定義中處理主鍵的邏輯是:

  1.如果表定義了主鍵,就使用主鍵唯一定位一條記錄

  2.如果沒有定義主鍵,Innodb就產生一個全域唯一的rowid來定位一條記錄

 

auto_increment的由來:

  1.Innodb強烈推薦在設計表中自訂一個主鍵,因為rowid是全域唯一的,所以如果有很多表沒有定義主鍵,就會在產生rowid上產生爭用。

      /* Dictionary system struct */      struct dict_sys_struct{      mutex_tmutex;      row_id_trow_id;      ......      }

  row_id由mutex保護,並在每次checkpoint的時候,寫入到資料字典的檔案頭。

  2.當使用者自訂了主鍵後,由於大部分實際應用部署的分布式,所以主索引值的產生上,採用集中式的方式,更容易實現唯一性,所以auto_increment非常合適。

  auto_increment也帶來兩個好處:

  1. auto_increment的值是表層級的,不會在db層級上產生爭用

  2. 由於auto_increment的順序性,減少了隨機讀的可能,保證了寫入的page的緩衝命中。(不可否認,寫入的並發足夠大時,會產生熱點塊的爭用)

 

auto_increment引起的bug:

  環境:MySQL 5.6.16版本, binlog_format=row

  case複現:

     create table test.kkk ( c int(11) default null, id int(11) not null auto_increment, d int(11) default null, primary key (id), unique key d (d) )     engine=innodb default charset=latin1;     insert into test.kkk values(5, 27,4);     replace into test.kkk(c, id, d) values(6, 35, 4);     commit;
     show create table時:     主庫:auto_increment=36     備庫:auto_increment=28

  當進行主備切換後,導致主鍵衝突,slave恢複異常。

  同樣insert on duplication update 語句同樣存在這樣的問題。

 

aliyun rds分支bug修複

  問題的原因:Innodb對於auto_increment的處理,當語句是insert時,會進行遞增,而update,delete語句則不更新。

  當replace語句在主庫的執行時:

  1. 先按照insert語句執行,發現uk衝突。

  2. 演變成update語句進行更新。

  這樣在主庫,雖然insert失敗,但auto_increment也遞增上去了。但到備庫,row格式下,只產生了一個update row event,

  備庫無法知道主庫是一個replace語句,而且insert還失敗了, 所以auto_increment在備庫沒有遞增。

  修複方式:在備庫,對於update進行auto_increment遞增,可能會產生副作用,即auto_increment的浪費,但不會產生主鍵衝突。

 

那些年經曆的auto_increment坑:

  1. 執行個體重啟,主鍵衝突:

  記憶體中的autoinc值,在系統重啟後,使用select max(id) from table來初始化。所以,如果你設計的業務表,存在delete操作,那麼一旦你的執行個體crash過,重啟後,可能會複用以前使用過的id值。如果你需要持續對這個表進行邏輯備份,那麼就可能會碰到主鍵衝突的問題。

 

  2. load file阻塞:

  在設定innodb_autoinc_lock_mode=1的時候,MySQL為了維護單個statement語句的id連續性,當不確定插入條數的時候,會在語句整個執行過程中

  持有LOCK_AUTO_INC, /* locks the auto-inc counter of a table in an exclusive mode */

  這個鎖是表層級的,使用互斥模式。

  所以,在繁忙的表上,如果要匯入資料,小心可能阻塞正常的業務寫入,並發寫入在這個時候也會阻塞的。

MySQL auto_increment的坑

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.