資料庫的四種隔離級別

2021-08-25 05:54:35 字數 3756 閱讀 5929

引用原文中關於資料庫四種隔離級別的介紹。

現代資料庫不會使用純粹的隔離作為預設模式,因為它會帶來巨大的效能消耗。sql一般定義4個隔離級別:

多數資料庫新增了自定義的隔離級別(比如 postgresql、oracle、sql server的快照隔離),而且並沒有實現sql規範裡的所有級別(尤其是讀取未提交級別)。

預設的隔離級別可以由使用者/開發者在建立連線時覆蓋(只需要增加很簡單的一行**)。

oracle支援兩種事務隔離級別:read committed(預設事務隔離級別),serializable。mysql支援四種事務隔離級別,其中repeatable read為預設事務隔離級別。

看到這個介紹簡直也是一頭霧水。直接做實驗來理解吧。

建立乙個balance表,裡面有一列資料money,咱們就玩id=1這一行的money,初始值為2960。

然後開啟兩個遠端登入的視窗,都開啟mysql資料庫,開始實驗。

從隔離級別低到高,分別是:讀取未提交、讀取已提交、可重複讀、序列化。

-- 視窗1

-- 視窗2

可見在視窗2這個事務中money已經被修改,但是還沒提交。

-- 視窗1

可見,雖然視窗2的事務還沒提交,但是視窗1的事務已經可以讀到還沒提交的資料,所以這就叫做讀取未提交。可以看到,兩個事務的隔離性很低,這是四種隔離級別中最低的級別。

-- 視窗2

money變回2960了。

-- 視窗1

-- 視窗2

-- 視窗1

-- 視窗2

-- 視窗1

select money from balance where id = 1;

commit;

-- 視窗1

-- 設定隔離級別為repeatable read

set session transaction isolation level repeatable read;

begin;

select money from balance where id = 1;

-- 視窗2

-- 修改money並提交

begin;

update balance set money = money - 1000;

select money from balance where id = 1;

commit;

-- 視窗1

-- 視窗1的事務還是視而不見。

select money from balance where id = 1;

-- 視窗1

-- 先是繼續用可重複讀的隔離級別。

begin;

select count(*) from balance;

好的,表裡有579條資料。然後我們在視窗2的事務中插入新資料。

-- 視窗2

-- 在視窗2的事務中插入新資料。

begin;

insert into balance (money) values (999);

commit;

select count(*) from balance;

好了,資料表中的記錄數已經達到了580條。那麼回到視窗1,按照可重複讀的定義,應該是580條記錄,然後序列化的設定才是579條記錄。可是! 

repeatable read:在mysql中,不會出現幻讀。mysql的實現和標準定義的rr隔離級別有差別。

好吧有興趣的同學可以看看這位大神的詳細解釋:mysql_repeatable-read事務隔離級別 && 幻讀。

資料庫四種隔離級別

存在的問題 更新遺失。解決辦法就是下面的 可讀取未確認 寫事務阻止其他寫事務,避免了更新遺失。但是沒有阻止其他讀事務。存在的問題 髒讀。即讀取到不正確的資料,因為另乙個事務可能還沒提交最終資料,這個讀事務就讀取了中途的資料,這個資料可能是不正確的。解決辦法就是下面的 可讀取確認 寫事務會阻止其他讀寫...

資料庫四種隔離級別

零 沒有併發控制 存在的問題 更新遺失。解決辦法就是下面的 可讀取未確認 一 可讀取未確認 read uncommitted 寫事務阻止其他寫事務,避免了更新遺失。但是沒有阻止其他讀事務。存在的問題 髒讀。即讀取到不正確的資料,因為另乙個事務可能還沒提交最終資料,這個讀事務就讀取了中途的資料,這個資...

資料庫的四種隔離級別

序列化 serializable,sqlite預設模式 最高端別的隔離。兩個同時發生的事務100 隔離,每個事務有自己的 世界 可重複讀 repeatable read,mysql預設模式 每個事務有自己的 世界 除了一種情況。如果乙個事務成功執行並且新增了新資料,這些資料對其他正在執行的事務是可見...