事務隔離級別總結

2022-09-09 16:33:29 字數 3495 閱讀 9333

事務(transaction)是資料庫系統中一系列操作的乙個邏輯單元,所有操作要麼全部成功要麼全部失

敗。 事務是區分檔案儲存系統與nosql資料庫重要特性之一,其存在的意義是為了保證即使在併發情況下也

能正確的執行crud操作。怎樣才算是正確的呢?這時提出了事務需要保證的四個特性即acid:

a:原子性(atomicity) 乙個事務中的所有操作,要麼全部完成,要麼全部不完成,不會結束在中間某個環節。事務在執行過程中發生錯誤,會被回滾(rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣。

c: 一致性(consistency) 在事務開始之前和事務結束以後,資料庫的完整性沒有被破壞。這表示寫入的資料必須完全符合所有的預設規則,這包含資料的精確度、串聯性以及後續資料庫可以自發性地完成預定的工作。

i:隔離性(isolation) 資料庫允許多個併發事務同時對其資料進行讀寫和修改的能力,隔離性可以防止多個事務併發執行 時由於交叉執行而導致資料的不一致。事務隔離分為不同級別,包括讀未提交(read uncommitted)、讀已提交(read committed)、可重複讀(repeatable read)和序列化(serializable)。

d:永續性(durability) 事務處理結束後,對資料的修改就是永久的,即便系統故障也不會丟失。

在高併發的情況下,要完全保證其acid特性是非常困難的,除非把所有的事務序列化執行,但帶來的負 面的影響將是效能大打折扣。很多時候我們有些業務對事務的要求是不一樣的,所以資料庫中設計了四 種隔離級別,供使用者基於業務進行選擇。這四種隔離級別分別是:

讀未提交(read uncommitted)

讀已提交(read committed)

可重複讀(repeatable read)

序列化(serializable)

其中,oracle預設的級別是read committed,而mysql預設為repeatable read。

注:mysql中檢視、設定事務隔離級別:

#檢視事務隔離級別

select @@tx_isolation;

#設定隔離級別為read-uncommitted

set tx_isolation='read-uncommitted';

髒讀(dirty read) 指乙個事務讀取到另一事務未提交的更新資料。

不可重複讀(nonrepeatable read) 指在同一事務中,多次讀取同一資料返回的結果有所不同。也就是說,後續讀取可以讀到另一事務已提交的更 新資料。相反, 可重複讀在同一事務中多次讀取資料時,能夠保證所讀資料一樣,也就是後續讀取不能讀到另一事務已提交的更新資料。

幻讀(phantom read) 指在同乙個事務中,多次讀取到的資料數量不一致。也就是說,後續讀取可以讀取到另乙個事務刪除或者新增的資料。 不可重複讀與幻讀在概念上容易混淆,其不同在於:不可重複讀側重的是另乙個事務對資料的修改,是行級別的操作。而幻讀側重的是另乙個事務對資料的新增或刪除,是整個表級別的操作。

採用不同的事務隔離級別,可解決不同的問題,總結如下:

髒讀不可重複讀

幻讀read uncommitted

不可解決

不可解決

不可解決

read committed

可解決不可解決

不可解決

repeatable read

可解決可解決

不可解決

serializable

可解決可解決

可解決可以看到,隔離級別越高,事務的安全性就越高,但是對效能的影響也越大,實際應用中應根據不同業務場景選擇不同的隔離級別。

準備 表結構:

create table `account` (

`id` int(11) not null auto_increment,

`name` varchar(32) not null,

`money` bigint(20) not null,

primary key (`id`)

) engine=innodb auto_increment=3 default charset=utf8mb4;

髒讀 開啟2個資料庫session,session1執行

#設定為讀未提交

set tx_isolation='read-uncommitted';

begin;

insert into `account` (`name`,`money`) values ('kobe',100);

此時session1向資料庫插入了一條資料,還未提交。 這時,在session2中讀取資料:

#設定為讀未提交

set tx_isolation='read-uncommitted';

select * from `account`;

不可重複讀 初始化資料:

insert into `account` (`name`,`money`) values ('kobe',100);

在session1中執行查詢:

#設定為讀已提交

set tx_isolation='read-committed';

begin;

select * from `account`;

# 其他操作

此時查詢到表中的資料是。

這時session2更新了表中的資料

#設定為讀已提交

set tx_isolation='read-committed';

update `account` set money= money+100 where `id`=1;

這時再在session1的當前事務中執行查詢:

select * from `account`; 

會發現資料已經變成了,也就是在同乙個事務中兩次讀取到的資料不一致,也即出現了不可重複讀。

幻讀 初始化資料:

insert into `account` (`name`,`money`) values ('kobe',); 

在session1中執行查詢:

#設定為可重複讀

set tx_isolation='repeatable-read';

begin;

select * from `account`;

此時,session2向表中插入一條資料:

#設定為可重複讀

set tx_isolation='repeatable-read';

insert into `account` (`name`,`money`) values ('james',100);

在session1的當前事務中再次執行查詢,會查詢到2條資料,好像憑空出現了一條資料一樣,也即出現了幻讀。

注:mysql innodb引擎通過next-key locks機制避免了幻讀的產生,因此mysql相當於採用預設的repeatable read級別就可以避免幻讀。具體可參考:

事務隔離級別總結

一 事務隔離級別 在資料庫系統中,隔離是定義乙個操作對資料所做的改變如何 何時對其它的並行操作可見。在資料庫操作中,為了有效保證併發讀取資料的正確性,提出的事務隔離級別。事務隔離級別 乙個事務對資料庫的修改與並行的另乙個事務的隔離程度。二 事務併發執行涉及到的問題 資料庫是要被廣大客戶所共享訪問的,...

事務隔離級別

1 serializable 最嚴格的spring事務隔離級別,事務序列執行,資源消耗最大 3 read committed 大多數主流資料庫的預設spring事務隔離等級,保證了乙個事務不會讀到另乙個並行事務已修改但未提交的資料,避免了 髒讀取 該級別適用於大多數系統。4 read uncommi...

事務隔離級別

四種隔離級別 隔離級別 髒 讀不可重複讀取 幻 像讀操作未提交 read uncommitted 是是 是讀操作已提交 read committed 否是 是可重複讀 repeatable read 否否 是快照否否 否可序列讀 serializable 否否 否 sql server 還支援使用行...