mysql业务数据库回退_理解MySQL数据库事务-隔离性
Transaction事務(wù)是指一個邏輯單元,執(zhí)行一系列操作的SQL語句。
事務(wù)中一組的SQL語句,要么全部執(zhí)行,要么全部回退。在Oracle數(shù)據(jù)庫中有個名字,叫做transaction ID
在關(guān)系型數(shù)據(jù)庫中,事務(wù)必須ACID的特性。
原子性,事務(wù)中的操作,要不全部執(zhí)行,要不都不執(zhí)行
一致性,事務(wù)完成前后,數(shù)據(jù)的必須保持一致。
隔離性,多個用戶并發(fā)訪問數(shù)據(jù)庫時,每一個用戶開啟的事務(wù),相互隔離,不被其他事務(wù)的操作所干擾。
持久性,事務(wù)一旦commit,它對數(shù)據(jù)庫的改變是持久性的。
目前重點討論隔離性。數(shù)據(jù)庫一共有四個隔離級別
未提交讀(RU,Read Uncommitted)。它能讀到一個事物的中間狀態(tài),不符合業(yè)務(wù)中安全性的保證,違背 了ACID特性,存在臟讀的問題,基本不會用到,可以忽略
提交讀(RC,Read Committed)。顧名思義,事務(wù)提交之后,那么我們可以看到。這是一種最普遍的適用的事務(wù)級別。我們生產(chǎn)環(huán)境常用的使用級別。
可重復(fù)讀(RR,Repeatable Read)。是目前被使用得最多的一種級別。其特點是有GAP鎖,目前還是默認級別,這個級別下會經(jīng)常發(fā)生死鎖,低并發(fā)等問題。
可串行化,這種實現(xiàn)方式,其實已經(jīng)是不是多版本了,而是單版本的狀態(tài),因為它所有的實現(xiàn)都是通過鎖來實現(xiàn)的。
因此目前數(shù)據(jù)庫主流常用的是RC和RR隔離級別。
隔離性的實現(xiàn)方式,我們通常用Read View表示一個事務(wù)的可見性。
RC級別,事務(wù)可見性比較高,它可以看到已提交的事務(wù)的所有修改。因此在提交讀(RC,Read Committed)隔離級別下,每一次select語句,都會獲取一次Read View,得到數(shù)據(jù)庫最新的事務(wù)提交狀態(tài)。因此對于數(shù)據(jù)庫,并發(fā)性能也最好。
RR級別,則不是。它為了避免幻讀和不可重復(fù)讀。保證在一個事務(wù)內(nèi)前后數(shù)據(jù)讀取的一致。其可見性視圖Read View只有在自己當前事務(wù)提交之后,才會更新。
那如何保證數(shù)據(jù)的一致性?其核心是通過redo log和undo log來保證的。
而在數(shù)據(jù)庫中,為了實現(xiàn)這種高并發(fā)訪問,就需要對數(shù)據(jù)庫進行多版本控制,通過事務(wù)的可見性來保證事務(wù)看到自己想看到的那個數(shù)據(jù)版本(或者是最新的Read View亦或者是老的Read View)。這種技術(shù)叫做MVCC
多版本是如何實現(xiàn)的?通過undo日志來保證。每一次數(shù)據(jù)庫的修改,undo日志會存儲之前的修改記錄值。如果事務(wù)未提交,會回滾至老版本的數(shù)據(jù)。其MVCC的核心原理,以后詳談
舉例論證:
##??開啟事務(wù)
MariaDB?[scott]>?begin;
Query?OK,?0?rows?affected?(0.000?sec)
##查看當前的數(shù)據(jù)
MariaDB?[scott]>??select?*?from?dept;
+--------+------------+----------+
|?deptno?|?dname??????|?loc??????|
+--------+------------+----------+
|?????10?|?ACCOUNTING?|?beijing??|
|?????20?|?RESEARCH???|?DALLAS???|
|?????30?|?SALES??????|?CHICAGO??|
|?????40?|?OPERATIONS?|?beijing??|
|?????50?|?security???|?beijing??|
|?????60?|?security???|?nanchang?|
+--------+------------+----------+
6?rows?in?set?(0.001?sec)
##更新數(shù)據(jù)
MariaDB?[scott]>?update?dept?set?loc?='beijing'?where?deptno?=?20;
Query?OK,?1?row?affected?(0.001?sec)
##?其行記錄|?20?|?RESEARCH?|?DALLAS?|已經(jīng)被放置在undo日志中,目前最新的記錄被改為'beijing':
MariaDB?[scott]>?select?*?from?dept;
+--------+------------+----------+
|?deptno?|?dname??????|?loc??????|
+--------+------------+----------+
|?????10?|?ACCOUNTING?|?beijing??|
|?????20?|?RESEARCH???|?beijing??|
|?????30?|?SALES??????|?CHICAGO??|
|?????40?|?OPERATIONS?|?beijing??|
|?????50?|?security???|?beijing??|
|?????60?|?security???|?nanchang?|
+--------+------------+----------+
##事務(wù)不提交,回滾。數(shù)據(jù)回滾至老版本的數(shù)據(jù)。
MariaDB?[scott]>?rollback;
Query?OK,?0?rows?affected?(0.004?sec)
MariaDB?[scott]>?select?*?from?dept;
+--------+------------+----------+
|?deptno?|?dname??????|?loc??????|
+--------+------------+----------+
|?????10?|?ACCOUNTING?|?beijing??|
|?????20?|?RESEARCH???|?DALLAS???|
|?????30?|?SALES??????|?CHICAGO??|
|?????40?|?OPERATIONS?|?beijing??|
|?????50?|?security???|?beijing??|
|?????60?|?security???|?nanchang?|
+--------+------------+----------+
6?rows?in?set?(0.000?sec)
因為MVCC,讓數(shù)據(jù)庫有了很強的并發(fā)能力。隨著數(shù)據(jù)庫并發(fā)事務(wù)處理能力大大增強,從而提高了數(shù)據(jù)庫系統(tǒng)的事務(wù)吞吐量,可以支持更多的用戶并發(fā)訪問。但并發(fā)訪問,會出現(xiàn)帶來一系列問題。如下:
數(shù)據(jù)庫并發(fā)帶來的問題
概述解釋
臟讀(Dirty Reads)
當一個事務(wù)A正在訪問數(shù)據(jù),并且對數(shù)據(jù)進行了修改,而這種修改還沒有提交到數(shù)據(jù)庫中,這時,另外一個事務(wù)B也訪問這同一個數(shù)據(jù),如不控制,事務(wù)B會讀取這些"臟"數(shù)據(jù),并可能做進一步的處理。這種現(xiàn)象被稱為"臟讀"(Dirty Reads)
不可重復(fù)讀(Non-Repeatable Reads)
指在一個事務(wù)A內(nèi),多次讀同一數(shù)據(jù)。在這個事務(wù)還沒有結(jié)束時,另外一個事務(wù)B也訪問該同一數(shù)據(jù)。那么,在事務(wù)A的兩次讀數(shù)據(jù)之間,由于第二個事務(wù)B的修改,那么第一個事務(wù)兩次讀到的的數(shù)據(jù)可能是不一樣的 。出現(xiàn)了"不可重復(fù)讀"(Non-Repeatable Reads)的現(xiàn)象
幻讀(Phantom Reads)
指在一個事務(wù)A內(nèi),按相同的查詢條件重新檢索以前檢索過的數(shù)據(jù),同時發(fā)現(xiàn)有其他事務(wù)插入了數(shù)據(jù),其插入的數(shù)據(jù)滿足事務(wù)A的查詢條件。因此查詢出了新的數(shù)據(jù),這種現(xiàn)象就稱為"幻讀"(Phantom Reads)
隔離級別和上述現(xiàn)象之間的聯(lián)系。
隔離級別有:未提交讀(RU,Read Uncommitted),提交讀(RC,Read Committed),可重復(fù)讀(RR,Repeatable Read),可串行化(Serializable)
隔離級別
臟讀
不可重復(fù)讀
幻讀
未提交讀(RU,Read Uncommitted)
可能
可能
可能
提交讀(RC,Read Committed)
不可能
可能
可能
可重復(fù)讀(RR,Repeatable Read)
不可能
不可能
可能
(間隙鎖解決)
可串行化(Serializable)
不可能
不可能
不可能
實驗環(huán)節(jié)
舉例在隔離級別RR和RC下,說明“不可重復(fù)讀”問題。
MySQL的默認級別是Repeatable Read,如下:
MariaDB?[(none)]>?select?@@global.tx_isolation;
+-----------------------+
|?@@global.tx_isolation?|
+-----------------------+
|?REPEATABLE-READ???????|
+-----------------------+
1?row?in?set?(0.000?sec)
這里修改當前會話級別為Read Committed
MariaDB?[scott]>?set?session?transaction?isolation?level?read?committed;
Query?OK,?0?rows?affected?(0.001?sec)
MariaDB?[scott]>?select?@@tx_isolation;
+----------------+
|?@@tx_isolation?|
+----------------+
|?READ-COMMITTED?|
+----------------+
1?row?in?set?(0.000?sec)
在隔離級別已提交讀(RC,Read Committed)下,出現(xiàn)了不可重復(fù)讀的現(xiàn)象。在事務(wù)A中可以讀取事務(wù)B中的數(shù)據(jù)。
在隔離級別可重復(fù)讀(RR,Repeatable Read),不會出現(xiàn)不可重復(fù)讀現(xiàn)象,舉例如下:
舉例說明“幻讀”的現(xiàn)象。
行鎖可以防止不同事務(wù)版本的數(shù)據(jù)在修改(update)提交時造成數(shù)據(jù)沖突的問題。但是插入數(shù)據(jù)如何避免呢?
在RC隔離級別下,其他事務(wù)的插入數(shù)據(jù),會出現(xiàn)幻讀(Phantom Reads)的現(xiàn)象。
而在RR隔離級別下,會通過Gap鎖,鎖住其他事務(wù)的insert操作,避免"幻讀"的發(fā)生。
因此,在MySQL事務(wù)中,鎖的實現(xiàn)方式與隔離級別有關(guān),如上述實驗所示。在RR隔離級別下,MySQL為了解決幻讀的問題,已犧牲并行度為代價,通過Gap鎖來防止數(shù)據(jù)的寫入。這種鎖,并行度差,沖突多。容易引發(fā)死鎖。
目前流行的Row模式可以避免很多沖突和死鎖問題,因此建議數(shù)據(jù)庫使用ROW+RC(Read Committed)模式隔離級別,很大程度上提高數(shù)據(jù)庫的讀寫并行度,提高數(shù)據(jù)庫的性能。
總結(jié)
以上是生活随笔為你收集整理的mysql业务数据库回退_理解MySQL数据库事务-隔离性的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 火狐 html5 退出 白屏,Html5
- 下一篇: 数组顺序的移动