1. 程式人生 > >資料庫併發機制和事務的隔離級別詳解

資料庫併發機制和事務的隔離級別詳解

本文將從以下4個方面來展開:

(1)事務的4大特性:

  • 原子性
  • 一致性
  • 隔離性
  • 永續性
(2)資料庫併發操作產生的問題:
  • 丟失更新
  • 髒讀
  • 不可重複讀
  • 幻讀
(3)資料庫的鎖機制:
  • 共享鎖
  • 排他鎖
  • 更新鎖
  • 悲觀鎖
  • 樂觀鎖
(4)事務的4大隔離級別:
  • read_uncommited (讀未提交)
  • read_commited(讀已提交)
  • repeatable_read (可重複讀)
  • Serialization   (序列讀)

1、事務的4大特性:


      事務是使用者定義的一個數據庫操作序列,這些操作要麼全做要麼全不做,是一個不可分割的工作單位。例如,在關係資料庫中,一個事務可以是一條SQL語句、一組SQL語句或整個程式。 事務和程式是兩個概念。一般地講,一個程式中包含多個事務。
事務的開始與結束可以由使用者顯式控制。如果使用者沒有顯式地定義事務,則由DBMS按預設規定自動劃分事 務。

在SQL語言中,定義事務的語句有三條: 
BEGIN TRANSACTION 
COMMIT 
ROLLBACK

事務具有4個屬性:原子性、一致性、隔離性、永續性。這四個屬性通常稱為ACID特性。

  • 原子性(Atomicity):事務作為一個整體被執行,包含在其中的對資料庫的操作要麼全部被執行,要麼都不執行。
  • 一致性(Consistency):事務應確保資料庫的狀態從一個一致狀態轉變為另一個一致狀態。一致狀態的含義是資料庫中的資料應滿足完整性約束。
  •  隔離性(Isolation):多個事務併發執行時,一個事務的執行不應影響其他事務的執行。
  •  永續性(Durability):一個事務一旦提交,他對資料庫的修改應該永久儲存在資料庫中。

2、資料庫併發操作產生的問題:

在多個事務併發做資料庫操作的時候,如果沒有有效的避免機制,就會出現種種問題。大體上有四種問題,歸結如下:

1、丟失更新:

如果兩個事務都要更新資料庫一個欄位X,X=100

兩個不同事物同時獲得相同資料,然後在各自事務中同時修改了該資料,那麼先提交的事務更新會被後提交事務的更新給覆蓋掉,這種情況事務A的更新就被覆蓋掉了、丟失了。


2、髒讀

防止一個事務讀到另一個事務還沒有提交的記錄。 如:

 

事務讀取了未提交的資料,事務B的回滾,導致了事務A的資料不一致,導致了事務A的髒讀 !

3、不可重複讀

一個事務在自己沒有更新資料庫資料的情況,同一個查詢操作執行兩次或多次的結果應該是一致的;如果不一致,就說明為不可重複讀。還是用上面的例子


這種情況事務A多次讀取x的結果出現了不一致,即為不可重複讀 。

4、幻讀

事務A讀的時候讀出了15條記錄,事務B在事務A執行的過程中 增加 了1條,事務A再讀的時候就變成了 16 條,這種情況就叫做幻影讀。


不可重複讀說明了做資料庫讀操作的時候可能會出現的問題。

提醒:
不可重複讀的重點是修改:
同樣的條件,你讀取過的資料,再次讀取出來發現值不一樣了
幻讀的重點在於新增或者刪除:
同樣的條件,第 1 次和第 2 次讀出來的記錄數不一樣

3、資料庫的鎖機制:

1、鎖的兩種分類方式

(1)從資料庫系統的角度來看,鎖分為以下三種類型:

mysql鎖機制分為表級鎖和行級鎖,行級鎖包括共享鎖、排他鎖和更新鎖。

 獨佔鎖,簡稱X鎖(Exclusive Lock)
      獨佔鎖鎖定的資源只允許進行鎖定操作的程式使用,其它任何對它的操作均不會被接受。執行資料更新命令,即INSERT、UPDATE 或DELETE 命令時,SQL Server 會自動使用獨佔鎖。但當物件上有其它鎖存在時,無法對其加獨佔鎖。獨佔鎖一直到事務結束才能被釋放。

 共享鎖,簡稱S鎖(Shared Lock)
      共享鎖鎖定的資源可以被其它使用者讀取,但其它使用者不能修改它。在SELECT 命令執行時,SQL Server 通常會對物件進行共享鎖鎖定。通常加共享鎖的資料頁被讀取完畢後,共享鎖就會立即被釋放。

 更新鎖(Update Lock)
      更新鎖是為了防止死鎖而設立的。當SQL Server 準備更新資料時,它首先對資料物件作更新鎖鎖定,這樣資料將不能被修改,但可以讀取。等到SQL Server 確定要進行更新資料操作時,它會自動將更新鎖換為獨佔鎖。但當物件上有其它鎖存在時,無法對其作更新鎖鎖定。

      對於共享鎖大家可能很好理解,就是多個事務只能讀資料不能改資料,對於排他鎖大家的理解可能就有些差別,我當初就犯了一個錯誤,以為排他鎖鎖住一行資料後,其他事務就不能讀取和修改該行資料,其實不是這樣的。排他鎖指的是一個事務在一行資料加上排他鎖後,其他事務不能再在其上加其他的鎖。mysql InnoDB引擎預設的修改資料語句,update,delete,insert都會自動給涉及到的資料加上排他鎖,select語句預設不會加任何鎖型別,如果加排他鎖可以使用select ...for update語句,加共享鎖可以使用select ... lock in share mode語句。所以加過排他鎖的資料行在其他事務種是不能修改資料的,也不能通過for update和lock in share mode鎖的方式查詢資料,但可以直接通過select ...from...查詢資料,因為普通查詢沒有任何鎖機制。

(2)從程式設計師的角度看,鎖分為以下兩種型別:

悲觀鎖(Pessimistic Lock)
      悲觀鎖,正如其名,它指的是對資料被外界(包括本系統當前的其他事務,以及來自外部系統的事務處理)修改持保守態度,因此在整個資料處理過程中,將資料處於鎖定狀態。悲觀鎖的實現,往往依靠資料庫提供的鎖機制(也只有資料庫層提供的鎖機制才能真正保證資料訪問的排他性,否則,即使在本系統中實現了加鎖機制,也無法保證外部系統不會修改資料)。

樂觀鎖(Optimistic Lock)
      相對悲觀鎖而言,樂觀鎖機制採取了更加寬鬆的加鎖機制。悲觀鎖大多數情況下依靠資料庫的鎖機制實現,以保證操作最大程度的獨佔性。但隨之而來的就是資料庫效能的大量開銷,特別是對長事務而言,這樣的開銷往往無法承受。
      而樂觀鎖機制在一定程度上解決了這個問題。樂觀鎖,大多是基於資料版本( Version )記錄機制實現。何謂資料版本?即為資料增加一個版本標識,在基於資料庫表的版本解決方案中,一般是通過為資料庫表增加一個 “version” 欄位來實現。讀取出資料時,將此版本號一同讀出,之後更新時,對此版本號加一。此時,將提交資料的版本資料與資料庫表對應記錄的當前版本資訊進行比對,如果提交的資料版本號大於資料庫表當前版本號,則予以更新,否則認為是過期資料。

      常見實現方式:在資料表增加version欄位,每次事務開始時將取出version欄位值,而後在更新資料的同時version增加1(如: update xxx set data=#{data},version=version+1 where version=#{version} ),如沒有資料被更新,那麼說明資料由其它的事務進行了更新,此時就可以判斷當前事務所操作的歷史快照資料。

4、事務的隔離級別:

 隔離級別:

為了避免資料庫事務操作中的問題,在標準SQL規範中,定義了4個事務隔離級別,不同的隔離級別對事務的處理不同:

  ◆讀未提交(Read Uncommitted):允許髒讀取,但不允許更新丟失。如果一個事務已經開始寫資料,則另外一個數據則不允許同時進行寫操作,但允許其他事務讀此行資料。該隔離級別可以通過“排他寫鎖”實現。


  ◆讀已提交(Read Committed):允許不可重複讀取,但不允許髒讀取。這可以通過“瞬間共享讀鎖”和“排他寫鎖”實現。讀取資料的事務允許其他事務繼續訪問該行資料,但是未提交的寫事務將會禁止其他事務訪問該行。


  ◆可重複讀(Repeatable Read):禁止不可重複讀取和髒讀取,但是有時可能出現幻影資料。這可以通過“共享讀鎖”和“排他寫鎖”實現。讀取資料的事務將會禁止寫事務(但允許讀事務),寫事務則禁止任何其他事務。


  ◆序列化(Serializable):提供嚴格的事務隔離。它要求事務序列化執行,事務只能一個接著一個地執行,但不能併發執行。如果僅僅通過“行級鎖”是無法實現事務序列化的,必須通過其他機制保證新插入的資料不會被剛執行查詢操作的事務訪問到。
  

       隔離級別越高,越能保證資料的完整性和一致性,但是對併發效能的影響也越大。對於多數應用程式,可以優先考慮把資料庫系統的隔離級別設為Read Committed,它能夠避免髒讀取,而且具有較好的併發效能。儘管它會導致不可重複讀、虛讀和第二類丟失更新這些併發問題,在可能出現這類問題的個別場合,可以由應用程式採用悲觀鎖或樂觀鎖來控制。

隔離級別實現機制:


x鎖 排他鎖 被加鎖的物件只能被持有鎖的事務讀取和修改,其他事務無法在該物件上加其他鎖,也不能讀取和修改該物件
s鎖 共享鎖 被加鎖的物件可以被持鎖事務讀取,但是不能被修改,其他事務也可以在上面再加s鎖。
 
在運用X鎖和S鎖對資料物件加鎖時,還需要約定一些規則 ,例如何時申請X鎖或S鎖、持鎖時間、何時釋放等。稱這些規則為封鎖協議(Locking Protocol)。對封鎖方式規定不同的規則,就形成了各種不同的封鎖協議。
  
   一級封鎖協議 (對應 read uncommited)  
   一級封鎖協議是:事務T在修改資料R之前必須先對其加X鎖,直到事務結束才釋放。事務結束包括正常結束(COMMIT)和非正常結束(ROLLBACK)。
   一級封鎖協議可以防止丟失修改,並保證事務T是可恢復的。使用一級封鎖協議可以解決丟失修改問題。   
   在一級封鎖協議中,如果僅僅是讀資料不對其進行修改,是不需要加鎖的,它不能保證可重複讀和不讀“髒”資料。
  
   二級封鎖協議 (對應read commited) 
   二級封鎖協議是:一級封鎖協議加上事務T在讀取資料R之前必須先對其加S鎖,讀完後方可釋放S鎖 
   二級封鎖協議除防止了丟失修改,還可以進一步防止讀“髒”資料。但在二級封鎖協議中,由於讀完資料後即可釋放S鎖,所以它不能保證可重複讀。
  
   三級封鎖協議 (對應reapetable read )
   三級封鎖協議是:一級封鎖協議加上事務T在讀取資料R之前必須先對其加S鎖,直到事務結束才釋放。  
   三級封鎖協議除防止了丟失修改和不讀“髒”資料外,還進一步防止了不可重複讀。

鎖和隔離級別的關係

        一般來說,實際開發中,直接操作資料庫中各種鎖的機率相對比較少,更多的是利用資料庫提供的四個隔離級別,未提交讀、已提交讀、可重複讀、可序列化,那隔離級別和鎖是什麼關係?通俗來說,隔離級別是鎖的一個整體打包解決方案,我的理解是隔離封裝了鎖。


       隔離級別從上到下依次增加,級別越低,引起的問題也就比較多,比如髒讀、丟失更新等,但等級越高,也就意味著需要管理更多的鎖,無法並行處理,效能方面又受損,因此,我們在設計系統時,只需要根據業務需求選擇一種當下適合的隔離級別。一種隔離級別,就有一套利用鎖的方案,如此設計,目的就是為了平衡效能和功能。

(多謝前人的總結)

轉載摘抄於以下網頁:

如果對你有幫助,記得點贊哦~歡迎大家關注我的部落格,可以進群366533258一起交流學習哦~奮鬥

相關推薦

資料庫併發機制事務隔離級別

本文將從以下4個方面來展開:(1)事務的4大特性:原子性一致性隔離性永續性(2)資料庫併發操作產生的問題:丟失更新髒讀不可重複讀幻讀(3)資料庫的鎖機制:共享鎖排他鎖更新鎖悲觀鎖樂觀鎖(4)事務的4大隔離級別:read_uncommited (讀未提交)read_commit

SQL Server 事務隔離級別

完成 sql 事務 create 事務隔離 測試數據 span read type off SQL 事務隔離級別 概述 隔離級別用於決定如果控制並發用戶如何讀寫數據的操作,同時對性能也有一定的影響作用。 步驟 事務隔離級別通過影響讀操作來間接地影響寫操作;可以在回

MySQL事務隔離級別

默認 多少 bcf 結構 有一個 個數 ref tle eat 轉載自: MySQL事務隔離級別詳解 SQL標準定義了4類隔離級別,包括了一些具體規則,用來限定事務內外的哪些改變是可見的,哪些是不可見的。低級別的隔離級一般支持更高的並發處理,並擁有更低的系統開銷。Read

事務隔離級別

增刪改 col 復讀 直接 提交 新的 bsp OS 不可 一、讀未提交。(A事務能夠讀取到B事務對數據的增刪改操作) 該事務級別會出現臟讀問題。 二、讀已提交。(該事務級別不會出現臟讀問題) 只要一個事務A提交了,那麽事務A中對數據庫表的增刪改操作,都會直接

mysql 事務隔離級別

bat con enc ron 問題 修改方法 復讀 get 很多 事物的 隔離級別,說簡單非常簡單(新手也能說出 是個隔離級別 和 影響),說男也非常難。(很多 有幾年編程 經驗的程序員依舊搞不清楚) 廢話不多少 直接開始: 事務的隔離級別 是用來描述

【轉】SQL Server 事務隔離級別

SQL 事務隔離級別 概述      隔離級別用於決定如果控制併發使用者如何讀寫資料的操作,同時對效能也有一定的影響作用。 步驟 事務隔離級別通過影響讀操作來間接地影響寫操作;可以在回話級別上設定事務隔離級別也可以在查詢(表級別)級別上設定事務隔離級別。事務隔離級別總共有6個隔離級別:READ UNC

Mysql的4種事務隔離級別

sql標準定義了4種隔離級別,包含了一些具體規則,用來限定事物內外的那些變化是可見的,哪些是不可見的。 低級別的隔離級一般支援更

【搞定MySQL資料庫】之事務的4種隔離級別

資料庫事務的隔離級別有4種,由低到高分別為Read uncommitted 、Read committed 、Repeatable read 、Serializable 。而且,在事務的併發操作中可能會出現髒讀,不可重複讀,幻讀。下面通過事例一一闡述它們的概念與聯絡。 1、讀未提交 

數據庫事務的四大特性事務隔離級別

簡單 個數 多個實例 tails ref 感覺 mvc 不能 變換 Reference: [1] http://www.cnblogs.com/fjdingsd/p/5273008.html [2] http://blog.csdn.net/fg2006/article/d

數據庫事務的四大特性以及事務隔離級別

idt fig mysq 復讀 臟讀 完成 避免 RF 發送 作者 : fjdingsd 來源 : 博客園 本篇講訴數據庫中事務的四大特性(ACID),並且將會詳細地說明事務的隔離級別。 如果一個數據庫聲稱支持事務的操作,那麽該數據庫必須要具備以下四個特性: ⑴ 原子性(

資料庫三大正規化及事務隔離級別

原文連結:https://www.cnblogs.com/linjiqin/archive/2012/04/01/2428695.html https://www.cnblogs.com/huanongying/p/7021555.html 在實際開發中最為常見的設計正規化有三個: 1.第一正規化(確保

資料庫併發問題 封鎖協議 隔離級別

序 此篇部落格是【眼見為實】系列的第一篇部落格,主要從理論上講了資料庫併發可能會出現的問題,解決併發問題的技術——封鎖,封鎖約定的規則——封鎖協議。然後簡單說明了資料庫事務隔離級別和封鎖協議的對應關係。後面的幾篇部落格都是通過親身實踐探究InnoDB引擎在各個隔離級

資料庫併發問題及事物隔離級別問題:髒讀,不可重複讀,幻讀,第一類丟失更新,第二類丟失更新

來源:《spring 4 企業應用開發實戰》 資料庫併發問題:髒讀,不可重複讀,幻讀,第一類丟失更新,第二類丟失更新 一個數據庫,多個客戶端併發訪問資料庫。在資料庫中的相同資料可能被多個事物同時訪問,如果沒有采取必要的隔離措施,就會導致併發問題,破壞資料的完整性。這些問題可以歸結為5類:3類

資料庫隔離級別

一、隔離級別及含義 事務隔離級別(transaction isolation levels):隔離級別就是對對事務併發控制的等級。ANSI/ ISO SQL將其分為序列化(SERIALIZABLE)、可重複讀(REPEATABLE READ)、讀已提交(READ COMM

spring事務傳播特性事務隔離級別

一、事務傳播特性 轉自:http://www.iteye.com/topic/35907 在所有使用 spring 的應用中, 宣告式事務管理可能是使用率最高的功能了, 但是, 從我觀察到的情況看, 絕大多數人並不能深刻理解事務宣告中不同事務傳播屬性配置的的含義, 讓我們

spring事務的傳播屬性事務隔離級別及配置事務(註解方式)

一、Propagation (事務的傳播屬性) Propagation :  key屬性確定代理應該給哪個方法增加事務行為。這樣的屬性最重要的部份是傳播行為。有以下選項可供使用:   PROPAGATION_REQUIRED--支援當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇。 PROPAG

spring 事務傳播行為事務隔離級別

1、Spring宣告式事務 宣告式事務(declarative transaction management)是Spring提供的對程式事務管理的方式之一。 Spring的宣告式事務顧名思義就是採用宣告的方式來處理事務。這裡所說的宣告,就是指在配置檔案中申明。用在Sp

事務隔離級別

一、事務的基本要素(ACID)   1、原子性(Atomicity):事務開始後所有操作,要麼全部做完,要麼全部不做,不可能停滯在中間環節。事務執行過程中出錯,會回滾到事務開始前的狀態,所有的操作就像沒有發生一樣。也就是說事務是一個不可分割的整體,就像化學中學過的原子,是物質構成的基

SQL Server事務隔離級別(二十九)

前言 事務一直以來是我最薄弱的環節,也是我打算重新學習SQL Server的出發點,關於SQL Server中事務將分為幾節來進行闡述,Always to review the basics。  事務簡介 事務是一個工作單元,可能包含查詢和修改資料以及修改資料定義等多個活動

mysql檢視鎖住的表事務隔離級別及儲存過程跳出迴圈處理方式

1、查詢是否鎖表 show OPEN TABLES where In_use > 0; 2、查詢程序 show processlist 查詢到相對應的程序,然後 kill id 檢視正在鎖的事務 SELECT *