事務(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中檢視、設定事務隔離級別:
#檢視事務隔離級別髒讀(dirty read) 指乙個事務讀取到另一事務未提交的更新資料。select @@tx_isolation;
#設定隔離級別為read-uncommitted
set tx_isolation='read-uncommitted';
不可重複讀(nonrepeatable read) 指在同一事務中,多次讀取同一資料返回的結果有所不同。也就是說,後續讀取可以讀到另一事務已提交的更 新資料。相反, 可重複讀在同一事務中多次讀取資料時,能夠保證所讀資料一樣,也就是後續讀取不能讀到另一事務已提交的更新資料。
幻讀(phantom read) 指在同乙個事務中,多次讀取到的資料數量不一致。也就是說,後續讀取可以讀取到另乙個事務刪除或者新增的資料。 不可重複讀與幻讀在概念上容易混淆,其不同在於:不可重複讀側重的是另乙個事務對資料的修改,是行級別的操作。而幻讀側重的是另乙個事務對資料的新增或刪除,是整個表級別的操作。
採用不同的事務隔離級別,可解決不同的問題,總結如下:
髒讀不可重複讀
幻讀read uncommitted
不可解決
不可解決
不可解決
read committed
可解決不可解決
不可解決
repeatable read
可解決可解決
不可解決
serializable
可解決可解決
可解決可以看到,隔離級別越高,事務的安全性就越高,但是對效能的影響也越大,實際應用中應根據不同業務場景選擇不同的隔離級別。
準備 表結構:
create table `account` (髒讀 開啟2個資料庫session,session1執行`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;
#設定為讀未提交此時session1向資料庫插入了一條資料,還未提交。 這時,在session2中讀取資料:set tx_isolation='read-uncommitted';
begin;
insert into `account` (`name`,`money`) values ('kobe',100);
#設定為讀未提交不可重複讀 初始化資料: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更新了表中的資料
#設定為讀已提交這時再在session1的當前事務中執行查詢:set tx_isolation='read-committed';
update `account` set money= money+100 where `id`=1;
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 還支援使用行...