MySQL自增鎖


最近在工作中遇到很多使用MySQL自帶的autoincrement函數作為發號器,在實際使用中當並發比較小的時候還沒有問題,一旦並發增加就會出現很多問題,特此進行如下總結。

一、自增配置

通過如下建表語句就可以完成自增的配置

CREATE TABLE `test_inc` (
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

二、修改自增大小

通過如下sql可以自動生成數字:

insert into test_inc values();

當增加3行后表中數據如下:

+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
+----+

CREATE TABLE `test_inc` (
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

使用 alter table test_inc auto_increment=10;將自增修改成10后再次插入的數據為10.

+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
| 10 |
| 11 |
+----+

三、自增幅度

自增幅度通過auto_increment_offset和auto_increment_increment這2個參數進行控制

set global auto_increment_increment=2;
set global auto_increment_offset=2;
set session auto_increment_increment=2;
set session auto_increment_offset=2;

生成偶數的自增

set global auto_increment_increment=2;
set global auto_increment_offset=1;
set session auto_increment_increment=2;
set session auto_increment_offset=1;

生成奇數的自增

auto_increment_offset表示起始數字

auto_increment_increment表示調動幅度(即每次增加n個數字,2就代表每次+2)

四、獲得最后一個數字

通過使用last_insert_id()函數可以獲得最后一個插入的數字

select last_insert_id();

五、自增鎖

如果存在自增字段,MySQL會維護一個自增鎖,和自增鎖相關的一個參數為(5.1.22版本之后加入)

innodb_autoinc_lock_mode:可以設定3個值,0,1,2

0:traditonal (每次都會產生表鎖)

1:consecutive (會產生一個輕量鎖,simple insert會獲得批量的鎖,保證連續插入)

2:interleaved (不會鎖表,來一個處理一個,並發最高)

ps:這個參數值控制InnoDB引擎的設置,所有Myisam均為traditonal,每次均會進行表鎖。但是Innodb會視參數不通二產生不通的鎖。目前MySQL默認的配置為1。

六、自增的過程

第一種,插入空值的時候

當innodb_autoinc_lock_mode=0時

1、申請AUTO_INC鎖

2、得到當前的AUTO_INCREMENT值n,並加1

3、執行插入操作,並將n寫入新增的對應字段中。

4、釋放AUTO_INC鎖。

第二種,插入已經有值的自增

 

1、插入第一條數據

2、如果失敗流程結束

3、如果成功,申請AUTO_INC鎖

4、調用set_max函數,修改AUTO_INCREMENT

5、語句結束,釋放AUTO_INC鎖

 

七、存在的問題

1、復制的問題

在innodb_autoinc_lock_mode=2的時候,由於是來一個分配一個,故當replication模式為SBR的時候,如果發生Bulk inserts會在分配的時候向其他insert分配,就會出現主從不一致的情況,但是如果改為RBR就不會出現這種情況。

也就是說在RBR模式下,innodb_autoinc_lock_mode=2是安全的,其他情況還是建議設置為1.

2、load data的問題

當使用load data語句的時候,就算innodb_autoinc_lock_mode=1也會退化回0,這是因為為了保證數據的一致性。首先要說一下load data的執行過程,在主庫上load data為原始SQL語句,而在從庫上會先將文件傳輸過去在tmp下生成臨時問題,然后在執行load data語句。為了保證主庫和從庫的自增ID的一致性,binlog中會有set insert_ID命令,標明這個load語句的第一行的自增ID值,這樣在表鎖的情況下,就可以保證一致性了。

八、insert的補充說明

1.“INSERT-like”:

INSERT, INSERTSELECT, REPLACE, REPLACESELECT, and LOAD DATA, INSERTVALUES(),VALUES()

2.“Simple inserts”

就是通過分析insert語句可以確定插入數量的insert語句, INSERT, INSERTVALUES(),VALUES()

3.“Bulk inserts”

就是通過分析insert語句不能確定插入數量的insert語句, INSERTSELECT, REPLACESELECT, LOAD DATA

4.“Mixed-mode inserts”

INSERT INTO t1 (c1,c2) VALUES (1,’a'), (NULL,’b'), (5,’c'), (NULL,’d');

INSERTON DUPLICATE KEY UPDATE

 

九、官方鏈接

http://dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_autoinc_lock_mode 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM