因此,正確的原子操作是真正被執(zhí)行過(guò)的。是物理執(zhí)行。
在當(dāng)前事務(wù)中確實(shí)能看到插入的記錄。最后只不過(guò)刪除了。但是AUTO_INCREMENT不會(huì)應(yīng)刪除而改變值。
1、為什么auto_increament沒(méi)有回滾?
因?yàn)閕nnodb的auto_increament的計(jì)數(shù)器記錄的當(dāng)前值是保存在存內(nèi)存中的,并不是存在于磁盤(pán)上,當(dāng)mysql server處于運(yùn)行的時(shí)候,這個(gè)計(jì)數(shù)值只會(huì)隨著insert改增長(zhǎng),不會(huì)隨著delete而減少。而當(dāng)mysql server啟動(dòng)時(shí),當(dāng)我們需要去查詢(xún)auto_increment計(jì)數(shù)值時(shí),mysql便會(huì)自動(dòng)執(zhí)行:SELECT MAX(id) FROM 表名 FOR UPDATE;語(yǔ)句來(lái)獲得當(dāng)前auto_increment列的最大值,然后將這個(gè)值放到auto_increment計(jì)數(shù)器中。所以就算 Rollback MySQL的auto_increament計(jì)數(shù)器也不會(huì)作負(fù)運(yùn)算。
2、MySQL的事務(wù)對(duì)表操作的時(shí)候是否是物理操作?
MySQL的事務(wù)是有redo和undo的,redo操作的所有信息都是記錄到 redo_log中,也就是說(shuō)當(dāng)一個(gè)事務(wù)做commit操作時(shí),需要先把這個(gè)事務(wù)的操作寫(xiě)到redo_log中,然后再把這些操作flush到磁盤(pán)上,當(dāng) 出現(xiàn)故障時(shí),只需要讀取redo_log,然后再重新flush到磁盤(pán)就行了。
而對(duì)于undo就比較麻煩,MySQL在處理事務(wù)時(shí),會(huì)在數(shù)據(jù)共享 表空間里申請(qǐng)一個(gè)段叫做segment段,用保存undo信息,當(dāng)在處理rollback,不是完完全全的物理undo,而是邏輯undo,就是說(shuō)會(huì)對(duì)之 前的操作進(jìn)行反操作,但是這些共享表空間是不進(jìn)行回收的。這些表空間的回收需要由mysql的master thread進(jìn)程來(lái)進(jìn)行回收。