1. 程式人生 > >Mysql 主鍵自增長問題小結

Mysql 主鍵自增長問題小結

在mysql中,主鍵有auto_increment來保證其自增長,如果我們自定義函式來表示auto_increment的話可以如下:

Sql程式碼 複製程式碼 收藏程式碼
  1. createfunction select_autoincrement_id() returnsint(11)
  2. begin
  3. selectmax(id)+1 from table_name;
  4. end
  1. createfunction select_autoincrement_id() returnsint(11)  
  2. begin
  3. selectmax(id)+1 from table_name;  
  4. end

但是,此方法會有併發方面的問題,如兩個事務中就可能獲取到同一個id而其中一個失敗,所以需要鎖表

Sql程式碼 複製程式碼 收藏程式碼
  1. createfunction select_autoincrement_id() returnsint(11)
  2. begin
  3. selectmax(id)+1 from table_name forupdate;
  4. end
  1. createfunction select_autoincrement_id() returnsint(11)  
  2. begin
  3. selectmax(id)+1 from table_name forupdate;  
  4. end

用此種方法的話可以實現一些複雜的自增長邏輯要求,比如在一個複合主鍵中,要求以其中一個主鍵為參照物,另一個主鍵重新從1開始自增長,但缺點是需要鎖表,在大併發環境中會影響一定的效率,在mysql 5.1.22版本之前,均是需要鎖表的,但在5.1.22版本之後,引入了一種新的方法來解決自增長的效率問題,

Sql程式碼 複製程式碼 收藏程式碼
  1. innodb_autoinc_lock_mode = 0(全部使用表鎖)
  2. innodb_autoinc_lock_mode = 1(預設,可預判行數時使用新方式,不可時使用表鎖)
  3. innodb_autoinc_lock_mode = 2(全部使用新方式)
  1. innodb_autoinc_lock_mode = 0(全部使用表鎖)  
  2. innodb_autoinc_lock_mode = 1(預設,可預判行數時使用新方式,不可時使用表鎖)  
  3. innodb_autoinc_lock_mode = 2(全部使用新方式)  
在級別1中,引入了一個輕量級的互斥量,在不同的事務中auto_increment總是可以獲取到最新的自增長主鍵值而不需要鎖表(感覺似乎有點違背mysql預設的事務隔離級別?),但對於無法提前獲知插入行數的sql依然需要鎖表,如insert...select... replace...select... load data 還是使用表鎖