數據庫通常借助日志來實現事務酝掩,常見的有undo log、redo log眷柔,undo/redo log都能保證事務特性期虾,這里主要是原子性和持久性,即事務相關的操作驯嘱,要么全做镶苞,要么不做,并且修改的數據能得到持久化
redo log(重做日志/物理日志):提供前滾操作(commit之后一定會被寫入磁盤),保證事務的持久性
undo log(回退日志/邏輯日志) :提供回滾操作(rollback 時能回到事務執(zhí)行之前),保證事務的一致性
-
redo log 和 undo log 是保證本地事務的鞠评,bin log 是用于主從復制的
-
MVCC: 讀不加鎖茂蚓,讀寫不沖突 事務版本號
會保存某個時間點上的數據快照。這意味著事務可以看到一個一致的數據視圖剃幌,不管他們需要跑多久聋涨。這同時也意味著不同的[事務]在同一個時間點看到的同一個表的數據可能是不同的(讀寫排斥問題): 讀取版本控制中的歷史數據
在 READ COMMITTED 和 REPEATABLE READ 隔離等級之下才會使用 MVCC
可重復讀事務隔離級別下,對于快照數據负乡,非鎖定一致讀總是讀取事務開始時的行數據版本
READ COMMITED 事務隔離級別下牍白,總是讀取最新的快照數據。
update語句中的where查詢 語句 讀取的都是最新的快照數據抖棘,最新的提交數據(無論在RR級別還是在RC級別都是這樣的機制)
select語句中的where查詢語句(不加 共享鎖或排他鎖的情況下)RR級別下在同一個事務中茂腥,讀到的數據是事務剛開始是的快照數據(不會幻讀,同一查詢語句在同一事務中得到結果相同)或者是在本事務中對數據進行的最新修改切省,RC級別下最岗,同一個事務中讀到的是當前最新的快照版本數據(其它事務對這數據已提交的修改,會出現幻讀)或者是在本事務中對數據進行的最新修改朝捆。
update語句相當于獲取排他鎖般渡,未獲得鎖的事務只能等待。
ReadView(快照):
在innodb中(默認repeatable read級別), 事務在begin/start transaction之后的第一條select讀操作后, 會創(chuàng)建一個快照(read view), 將當前系統(tǒng)中活躍的其他事務記錄記錄起來;
-
在innodb中(默認repeatable committed級別), 事務中每條select語句都會創(chuàng)建一個快照(read view)
MVCC 存在的問題: 讀取舊版本數據,并以此來更新數據,導致更新丟失: 寫寫沖突問題
-
行鎖:只有通過索引條件檢索數據芙盘,InnoDB才使用行級鎖驯用,否則,InnoDB將使用表鎖何陆!
事務級行鎖: 執(zhí)行更新語句時加鎖,事務結束時解鎖
可重復讀的MVCC機制: 事務內兩次相同讀取的版本號一致
-
事務可能讀到的數據不是最新的,需保證只有是最新的數據才能被更新:MVCC+鎖
可重復讀級別下: mvcc 快照讀取的可能為舊數據,以舊數據進行更新時,更新操作會獲取到當前讀新數據,只需要保證新舊數據版本號一致才能更新,即可避免更新丟失問題,簡單來說:不提供舊版本數據的寫操作
可重復讀的底層原理: 排它鎖+MVCC 避免了第二類更新丟失問題
//查詢語句 + 排他鎖 : 一個事務內先查詢后更新,可以通過這個方法簡單實現互斥 select * from demo where id = 1 for update;
-
間隙鎖機制:幻讀 next-key鎖其實包含了記錄鎖和間隙鎖晨汹,即鎖定一個范圍,并且鎖定記錄本身贷盲,InnoDB默認加鎖方式是next-key 鎖