徹底理解事務的4個隔離級別

来源:http://www.cnblogs.com/jycboy/archive/2017/04/07/transaction.html
-Advertisement-
Play Games

簡介 在DBMS中,事務保證了一個操作序列可以全部都執行或者全部都不執行(原子性),從一個狀態轉變到另外一個狀態(一致性)。由於事務滿足久性。所以一旦事務被提交之後,數據就能夠被持久化下來,又因為事務是滿足隔離性的,所以,當多個事務同時處理同一個數據的時候,多個事務直接是互不影響的,所以,在多個事務 ...


簡介

在DBMS中,事務保證了一個操作序列可以全部都執行或者全部都不執行(原子性),從一個狀態轉變到另外一個狀態(一致性)。由於事務滿足久性。所以一旦事務被提交之後,數據就能夠被持久化下來,又因為事務是滿足隔離性的,所以,當多個事務同時處理同一個數據的時候,多個事務直接是互不影響的,所以,在多個事務併發操作的過程中,如果控制不好隔離級別,就有可能產生臟讀、不可重覆讀或者幻讀等讀現象。

在資料庫事務的ACID四個屬性中,隔離性是一個最常放鬆的一個。可以在數據操作過程中利用資料庫的鎖機制或者多版本併發控制機制獲取更高的隔離等級。但是,隨著資料庫隔離級別的提高,數據的併發能力也會有所下降。所以,如何在併發性和隔離性之間做一個很好的權衡就成了一個至關重要的問題。

資料庫事務的隔離級別有4個,由低到高依次為Read uncommitted、Read committed、Repeatable read、Serializable,這四個級別可以逐個解決臟讀、不可重覆讀、幻讀這幾類問題。

註意:我們討論隔離級別的場景,主要是在多個事務併發的情況下,因此,接下來的講解都圍繞事務併發。

Read uncommitted

讀未提交,顧名思義,就是一個事務可以讀取另一個未提交事務的數據。

事例:老闆要給程式員發工資,程式員的工資是3.6萬/月。但是發工資時老闆不小心按錯了數字,按成3.9萬/月,該錢已經打到程式員的戶口,但是事務還沒有提交,就在這時,程式員去查看自己這個月的工資,發現比往常多了3千元,以為漲工資了非常高興。但是老闆及時發現了不對,馬上回滾差點就提交了的事務,將數字改成3.6萬再提交。

分析:這種情況就是臟讀,兩個併發的事務,"事務A":領導發工資、"事務B":程式員查看工資,事務B讀取了事務A尚未提交的數據實際程式員這個月的工資還是3.6萬,但是程式員看到的是3.9萬。

未提交讀的資料庫鎖情況(實現原理)

事務在讀數據的時候並未對數據加鎖。

事務在修改數據的時候只對數據增加行級共用鎖

表現:

    • 事務1讀取某行記錄時,事務2也能對這行記錄進行讀取、更新;當事務2對該記錄進行更新時,事務1再次讀取該記錄,能讀到事務2對該記錄的修改版本,即使該修改尚未被提交。
    • 事務1更新某行記錄時,事務2不能對這行記錄做更新,直到事務1結束。

舉例

設置 set session transaction isolation level read uncommitted;

        set autocommit=0; 

下麵還是借用我在資料庫的讀現象淺析一文中舉的例子來說明在未提交讀的隔離級別中兩個事務之間的隔離情況。

事務一事務二
/* Query 1 */

SELECT age FROM users WHERE id = 1;

/* will read 20 */
 
 
/* Query 2 */
 
UPDATE users SET age = 21 WHERE id = 1;

/* No commit here */

/* Query 1 */

SELECT age FROM users WHERE id = 1;
/* will read 21 */
 
 
ROLLBACK;

/* lock-based DIRTY READ */

事務一共查詢了兩次,在兩次查詢的過程中,事務二對數據進行了修改,並未提交(commit)。但是事務一的第二次查詢查到了事務二的修改結果。在資料庫的讀現象淺析中我們介紹過,這種現象我們稱之為臟讀。

所以,未提交讀會導致臟讀

事務1更新某行記錄時,事務2不能對這行記錄做更新,直到事務1結束:

可以看到右邊更新一個記錄時,還沒有提交;

此時,左邊的事務二也對這條記錄更新,會阻塞。


Read committed

提交讀,顧名思義,就是一個事務要等另一個事務提交後才能讀取數據。

事例:程式員拿著信用卡去享受生活(卡裡當然是只有3.6萬),當他埋單時(程式員事務開啟),收費系統事先檢測到他的卡裡有3.6萬,就在這個時候!!程式員的妻子要把錢全部轉出充當家用,並提交。當收費系統準備扣款時,再檢測卡裡的金額,發現已經沒錢了(第二次檢測金額當然要等待妻子轉出金額事務提交完)。程式員就會很鬱悶,明明卡裡是有錢的…

分析:這就是提交讀,若有事務對數據進行更新(UPDATE)操作時,讀操作事務要等待這個更新操作事務提交後才能讀取數據,可以解決臟讀問題。但在這個事例中,出現了一個事務範圍內兩個相同的查詢卻返回了不同數據,這就是不可重覆讀

提交讀的資料庫鎖情況(實現原理)

事務對當前被讀取的數據加 行級共用鎖(當讀到時才加鎖),一旦讀完該行,立即釋放該行級共用鎖;

事務在更新某數據的瞬間(就是發生更新的瞬間),必須先對其加 行級排他鎖,直到事務結束才釋放。

舉例

事務一事務二
/* Query 1 */

SELECT * FROM users WHERE id = 1;
 
 
/* Query 2 */
 
UPDATE users SET age = 21 WHERE id = 1;

COMMIT;


/* in multiversion concurrency
control, or lock-based READ COMMITTED */


/* Query 1 */

SELECT * FROM users WHERE id = 1

lock in share mode;

COMMIT; 

/*lock-based REPEATABLE READ */

 

**在事務二沒有提交之前,事務一是不能更改這條記錄的,也不可以加共用鎖(lock in share mode)。只能執行普通的查詢

在提交讀隔離級別中,在事務二提交之前,事務一不能讀取數據。只有在事務二提交之後,事務一才能讀數據。

但是從上面的例子中我們也看到,事務一兩次讀取的結果並不一致,所以提交讀不能解決不可重覆讀的讀現象

簡而言之,提交讀這種隔離級別保證了讀到的任何數據都是提交的數據,避免了臟讀(dirty reads)。但是不保證事務重新讀的時候能讀到相同的數據,因為在每次數據讀完之後其他事務可以修改剛纔讀到的數據。


Repeatable read

重覆讀,就是在開始讀取數據(事務開啟)時,不再允許修改操作

事例:程式員拿著信用卡去享受生活(卡裡當然是只有3.6萬),當他買單時(事務開啟,不允許其他事務的UPDATE修改操作),收費系統事先檢測到他的卡裡有3.6萬。這個時候他的妻子不能轉出金額了。接下來收費系統就可以扣款了。

分析:重覆讀可以解決不可重覆讀問題。寫到這裡,應該明白的一點就是,不可重覆讀對應的是修改,即UPDATE操作。但是可能還會有幻讀問題。因為幻讀問題對應的是插入INSERT操作,而不是UPDATE操作。

可重覆讀的資料庫鎖情況

事務在讀取某數據的瞬間(就是開始讀取的瞬間),必須先對其加 行級共用鎖,直到事務結束才釋放;

事務在更新某數據的瞬間(就是發生更新的瞬間),必須先對其加 行級排他鎖,直到事務結束才釋放。

現象

事務1在讀取某行記錄的整個過程中,事務2都可以對該行記錄進行讀取(因為事務一對該行記錄增加行級共用鎖的情況下,事務二同樣可以對該數據增加共用鎖來讀數據。)。

事務1在讀取某行記錄的整個過程中,事務2都不能修改該行數據(事務一在讀取的整個過程會對數據增加共用鎖,直到事務提交才會釋放鎖,所以整個過程中,任何其他事務都不能對該行數據增加排他鎖。所以,可重覆讀能夠解決不可重覆讀的讀現象)

舉例

事務一事務二
/* Query 1 */

SELECT * FROM users WHERE id = 1;


COMMIT;
 
 
/* Query 2 */
 
UPDATE users SET age = 21 WHERE id = 1;

COMMIT;


/* in multiversion concurrency
control, or lock-based READ COMMITTED */

在上面的例子中,只有在事務一提交之後,事務二才能更改該行數據。所以,只要在事務一從開始到結束的這段時間內,無論他讀取該行數據多少次,結果都是一樣的。


幻讀

事例:程式員某一天去消費,花了2千元,然後他的妻子去查看他今天的消費記錄(全表掃描FTS,妻子事務開啟),看到確實是花了2千元,就在這個時候,程式員花了1萬買了一部電腦,即新增INSERT了一條消費記錄,並提交。當妻子列印程式員的消費記錄清單時(妻子事務提交),發現花了1.2萬元,似乎出現了幻覺,這就是幻讀。

事務一:妻子去查看消費記錄,事務一的兩次範圍查詢結果並不相同。這也就是我們提到的幻讀。

可重覆讀隔離級別可以解決不可重覆讀的讀現象,但是解決不了幻讀。解決幻讀需要序列化。


Serializable 序列化

Serializable 是最高的事務隔離級別,在該級別下,事務串列化順序執行,可以避免臟讀、不可重覆讀與幻讀。但是這種事務隔離級別效率低下,比較耗資料庫性能,一般不使用。

可序列化的資料庫鎖情況

事務在讀取數據時,必須先對其加 表級共用鎖 ,直到事務結束才釋放;

事務在更新數據時,必須先對其加 表級排他鎖 ,直到事務結束才釋放。


值得一提的是:大多數資料庫預設的事務隔離級別是Read committed,比如Sql Server , Oracle。MySQL的預設隔離級別是Repeatable read

 參考文章:

深入分析事務的隔離級別

理解事務的4種隔離級別

轉發請註明出處:http://www.cnblogs.com/jycboy/p/transaction.html

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • OpenCV是一個基於BSD許可(開源)發行的跨平臺電腦視覺庫,可以運行在Linux、Windows、Android和Mac OS操作系統上。它輕量級而且高效——由一系列 C 函數和少量 C++ 類構成,同時提供了Python、Ruby、MATLAB等語言的介面,實現了圖像處理和電腦視覺方面的很 ...
  • 轉載請標明出處 "http://www.cnblogs.com/yxx123/p/6675567.html" 防止連續點擊的實現方式有很多種,比如,在所有的onclick裡面加上防多次點擊的代碼,或者定義一個新的OnClickListener,在裡面加上防多次點擊的代碼,然後項目中的所有OnClic ...
  • 最近的項目要用到一個線上報告的下載,於是完成後自己在理一下思路,大體的實現了我要得需求。 話不多說,直接上代碼 首先,取到網路文件的鏈接,進行判段是否需求再次下載還是直接打開 #pragma mark 下載報告 //// 第一步 //是否下載還是打開文件 - (void)downloadPDF:(N ...
  • Windows下MongoDB的下載、安裝以及對應的windows服務的創建 ...
  • 本文出處:http://www.cnblogs.com/wy123/p/6677073.html 在做數據統計類資料庫設計的時候,在考慮數據存儲的時候,經常會遇到邏輯上同一個BusinessID對應多個數據點的情況,比如工資表中的員工ID以及各項工資信息,財務表中的各個報表Id和多個數據點之間的信息 ...
  • Util包下的連接資料庫的工具包 src下的jdbc.properties ...
  • 資料庫的主鍵與外鍵 一、什麼是主鍵、外鍵: 關係型資料庫中的一條記錄中有若幹個屬性,若其中某一個屬性組(註意是組)能唯一標識一條記錄,該屬性組就可以成為一個主鍵 比如 學生表(學號,姓名,性別,班級) 其中每個學生的學號是唯一的,學號就是一個主鍵 課程表(課程編號,課程名,學分) 其中課程編號是唯一 ...
  • 上篇文章介紹了關於MySQL如何配置主從複製,本篇主要說一下主主複製: 先對文章將要出現的關鍵詞做一下說明: server1、server2、server...表示資料庫伺服器 (寫的比較懶,用心體會) mysql主主複製配置server1 ip:192.168.0.231server2 ip:19 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...