為什么mysql事務回滾后, 自增ID依然自增


事務回滾后,自增ID仍然增加,回滾后,自增ID仍然增加。
比如當前ID是7,插入一條數據后,又回滾了。然后你再插入一條數據,此時插入成功,這時候你的ID不是8,而是9。因為雖然你之前插入回滾,但是ID還是自增了。

如果你認為自增ID不應該被事務化,那么其他事務不得不等待着,檢查自增ID是被使用還是被回滾,這就導致阻塞。

比如下面的例子,A表使用自增ID。

User 1
------------
begin transaction
insert into A ...
insert into B ...
update C ...
insert into D ...
commit
User 2
-----------
begin transaction
insert into A ...
insert into B ...
commit

看以上的例子代碼,如果自增ID也要被事務化,那么假設user 2 的事務在user 1執行后的1毫秒后執行,那么他的插入到A表不得不等待User 1的整個事務結束,檢查第一個自增ID是不是被使用了,這就導致阻塞。

自增ID不被事務化是設計使然,不是bug,如果需要緊密連續的自增序列,建議采用其他方法生成。

 

mysql事務回滾數據回滾用法與問題
mysql事務回滾就是BEGIN,ROLLBACK,COMMIT三種組成了,差不就是就如果所有數據提交成功再把數據提交,否則就自動回滾數據了,這種做法多做於銀行,種大大型數據操作應用上。

在當前事務中確實能看到插入的記錄。最后只不過刪除了。但是AUTO_INCREMENT不會應刪除而改變值。

1、為什么auto_increament沒有回滾?

因為innodb的auto_increament的計數器記錄的當前值是保存在存內 存中的,並不是存在於磁盤上,當mysql server處於運行的時候,這個計數值只會隨着insert改增長,不會隨着delete而減少。而當mysql server啟動時,當我們需要去查詢auto_increment計數值時,mysql便會自動執行:SELECT MAX(id) FROM 表名 FOR UPDATE;語句來獲得當前auto_increment列的最大值,然后將這個值放到auto_increment計數器中。所以就算 Rollback MySQL的auto_increament計數器也不會作負運算。

2、MySQL的事務對表操作的時候是否是物理操作?

MySQL的事務是有redo和undo的,redo操作的所有信息都是記錄到 redo_log中,也就是說當一個事務做commit操作時,需要先把這個事務的操作寫到redo_log中,然后再把這些操作flush到磁盤上,當 出現故障時,只需要讀取redo_log,然后再重新flush到磁盤就行了。
而對於undo就比較麻煩,MySQL在處理事務時,會在數據共享 表空間里申請一個段叫做segment段,用保存undo信息,當在處理rollback,不是完完全全的物理undo,而是邏輯undo,就是說會對之 前的操作進行反操作,但是這些共享表空間是不進行回收的。這些表空間的回收需要由mysql的master thread進程來進行回收。

 

參考:

mysql事務回滾數據回滾用法與問題  http://www.111cn.net/database/mysql/53781.htm

事務回滾后,自增ID仍然增加 http://www.2cto.com/database/201107/96110.html

轉自:https://blog.csdn.net/guyue35/article/details/53884073


免責聲明!

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



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