MySQL InnoDB事務隔離級別髒讀、可重複讀、幻讀
望通過本文,可以加深讀者對ySQL InnoDB的四個事務隔離級別,以及髒讀、不重複讀、幻讀的理解。
有四級,預設是“可重複讀”(REPEATABLE READ)。
· 未提交讀(READUNCOMMITTED)。另一個事務修改了資料,但尚未提交,而本事務中的SELECT會讀到這些未被提交的資料(髒讀)。
· 提交讀(READCOMMITTED)。本事務讀取到的是最新的資料(其他事務提交後的)。問題是,在同一個事務裡,前後兩次相同的SELECT會讀到不同的結果(不重複讀)。
· 可重複讀(REPEATABLEREAD
· 序列化(SERIALIZABLE)。讀操作會隱式獲取共享鎖,可以保證不同事務間的互斥。
四個級別逐漸增強,每個級別解決一個問題。
· 髒讀,最容易理解。另一個事務修改了資料,但尚未提交,而本事務中的SELECT會讀到這些未被提交的資料。
· 不重複讀。解決了髒讀後,會遇到,同一個事務執行過程中,另外一個事務提交了新資料,因此本事務先後兩次讀到的資料結果會不一致。
·
MySQL InnoDB事務隔離級別可設定為global和session級別。
事務隔離級別檢視
檢視當前session的事務隔離級別:
- mysql> show variables like'%tx_isolation%';
- +---------------+--------------+
-
| Variable_name | Value |
- +---------------+--------------+
- | tx_isolation | SERIALIZABLE |
- +---------------+--------------+
設定global事務隔離級別:
set global isolation level read committed;
注意一點的設定global並不會對當前session生效。
設定session事務隔離級別sql指令碼:
- set session transactionisolationlevelreaduncommitted;
- set session transactionisolationlevelreadcommitted;
- set session transactionisolationlevelREPEATABLEREAD;
- set session transactionisolationlevelSERIALIZABLE;
上面的文字,讀起來並不是那麼容易讓人理解,以下用幾個實驗對InnoDB的四個事務隔離級別做詳細的解釋,希望通過實驗來加深大家對InnoDB的事務隔離級別理解。
- CREATETABLE `t` (
- `a` INT (11) NOTNULLPRIMARYKEY
- ) ENGINE = INNODB DEFAULT CHARSET = UTF8;
- INSERTINTO t (a) VALUES (1),(2),(3);
實驗一:解釋髒讀、可重複讀問題
更新事務 |
事務A READ-UNCOMMITTED |
事務B READ-COMMITTED, |
事務C-1 REPEATABLE-READ |
事務C-2 REPEATABLE-READ |
事務D SERIALIZABLE |
set autocommit =0; |
|||||
start transaction ; |
start transaction; |
||||
insert into t(a)values(4); |
|||||
select * from t; 1,2,3,4(髒讀:讀取到了未提交的事務中的資料) |
select * from t; 1,2,3(解決髒讀) |
select * from t; 1,2,3 |
select * from t; 1,2,3 |
select * from t; 1,2,3 |
|
commit; |
|||||
select * from t: 1,2,3,4 |
select * from t: 1,2,3,4 |
select * from t: 1,2,3,4 (與上面的不在一個事務中,所以讀到為事務提交後最新的,所以可讀到4) |
select * from t: 1,2,3(重複讀:由於與上面的在一個事務中,所以只讀到事務開始事務的資料,也就是重複讀) |
select * from t: 1,2,3,4 |
|
commit(提交事務,下面的就是一個新的事務,所以可以讀到事務提交以後的最新資料) |
|||||
select * from t: 1,2,3,4 |
|||||
READ-UNCOMMITTED 會產生髒讀,基本很少適用於實際場景,所以基本不使用。 |
實驗二:測試READ-COMMITTED與REPEATABLE-READ
事務A |
事務B READ-COMMITTED |
事務C REPEATABLE-READ |
set autocommit =0; |
||
start transaction ; |
start transaction; |
start transaction; |
insert into t(a)values(4); |
||
select * from t; 1,2,3 |
select * from t; 1,2,3 |
|
commit; |
||
select * from t: 1,2,3,4 |
select * from t: 1,2,3(重複讀:由於與上面的在一個事務中,所以只讀到事務開始事務的資料,也就是重複讀) |
|
commit(提交事務,下面的就是一個新的事務,所以可以讀到事務提交以後的最新資料) |
||
select * from t: 1,2,3,4 |
||
REPEATABLE-READ可以確保一個事務中讀取的資料是可重複的,也就是相同的讀取(第一次讀取以後,即使其他事務已經提交新的資料,同一個事務中再次select也並不會被讀取)。 READ-COMMITTED只是確保讀取最新事務已經提交的資料。 |
當然資料的可見性都是對不同事務來說的,同一個事務,都是可以讀到此事務中最新資料的。
- start transaction;
- insertinto t(a) values (4);
- select * from t;
- 1,2,3,4;
- insertinto t(a) values (5);
- select * from t;
- 1,2,3,4,5;
實驗三:測試SERIALIZABLE事務對其他的影響
事務A SERIALIZABLE |
事務B READ-UNCOMMITTED |
事務C READ-COMMITTED, |
事務D REPEATABLE-READ |
事務E SERIALIZABLE |
set autocommit =0; |
||||
start transaction ; |
start transaction; |
|||
select a from t union all select sleep(1000) from dual; |
||||
insert into t(a)values(5); |
insert into t(a)values(5); |
insert into t(a)values(5); |
insert into t(a)values(5); |
|
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction |
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction |
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction |
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction |
|
SERIALIZABLE 序列化執行,導致所有其他事務不得不等待事務A結束才行可以執行,這裡特意使用了sleep函式,直接導致事務B,C,D,E等待事務A持有釋放的鎖。由於我sleep了1000秒,而innodb_lock_wait_timeout為120s。所以120s到了就報錯HY000錯誤。 |
||||
SERIALIZABLE是相當嚴格的序列化執行模式,不管是讀還是寫,都會影響其他讀取相同的表的事務。是嚴格的表級讀寫排他鎖。也就失去了innodb引擎的優點。實際應用很少。 |
實驗四:幻讀
一些文章寫到InnoDB的可重複讀避免了“幻讀”(phantom read),這個說法並不準確。
做個試驗:(以下所有試驗要注意儲存引擎和隔離級別)
- mysql>show createtable t_bitfly\G;
- CREATETABLE `t_bitfly` (
- `id` bigint(20) NOTNULLdefault'0',
- `value` varchar(32) defaultNULL,
- PRIMARYKEY (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=gbk
- mysql>select @@global.tx_isolation, @@tx_isolation;
- +-----------------------+-----------------+
- | @@global.tx_isolation | @@tx_isolation |
- +-----------------------+-----------------+
- | REPEATABLE-READ | REPEATABLE-READ |
- +-----------------------+-----------------+
試驗4-1:
- SessionA Session B
- START TRANSACTION; START TRANSACTION;
- SELECT * FROM t_bitfly;
- empty set
- INSERTINTO t_bitfly VALUES (1, 'a');
- SELECT * FROM t_bitfly;
- empty set
- COMMIT;
- SELECT * FROM t_bitfly;
- empty set
- INSERTINTO t_bitfly VALUES (1, 'a');
- ERROR 1062 (23000):
- Duplicate entry '1'forkey 1
v (shit, 剛剛明明告訴我沒有這條記錄的)
如此就出現了幻讀,以為表裡沒有資料,其實資料已經存在了,傻乎乎的提交後,才發現數據衝突了。
試驗4-2:
- SessionA Session B
-
START TRANSACTION; START
相關推薦
MySQL InnoDB事務隔離級別髒讀、可重複讀、幻讀
望通過本文,可以加深讀者對ySQL InnoDB的四個事務隔離級別,以及髒讀、不重複讀、幻讀的理解。 有四級,預設是“可重複讀”(REPEATABLE READ)。 · 未提交讀(READUNCOMMITTED)。另一個事務修改了資料
mysql-Innodb事務隔離級別-repeatable read詳解
經驗總結: python使用MySQLdb資料庫後,如使用多執行緒,每個執行緒建立一個db連結,然後再各自建立一個遊標cursor,其中第一個執行緒讀一個表中資料為空,第二個寫入該表一條資料並提交,第一個執行緒再讀該表資料將仍然無法讀出。和多資料庫的事務級別應該有關係;還可
資料庫事務隔離級別-- 髒讀、幻讀、不可重複讀(清晰解釋)
一、資料庫事務隔離級別 資料庫事務的隔離級別有4個,由低到高依次為Read uncommitted 、Read committed 、Repeatable read 、Serializable ,這四個級別可以逐個解決髒讀 、不可重複讀 、幻讀 這幾類問題。 √: 可能出
資料庫事務隔離級別-- 髒讀、幻讀、不可重複讀
一 、資料庫事務隔離級別 從高到低: 序列化 serilizable 消耗資源比較嚴重 重複讀 repeatable read Oracle 預設的事務隔離級別 讀提交 read committed Mysql 預設的隔離級別
從MySQL預設事務隔離級別(RR)到InnoDB非鎖定一致性讀
說到資料庫的隔離級別,我想大家都能說出一二,但是很多時候都是從網上看來的,很多都點到為止不夠詳細,並且沒有經過實踐的檢驗,所以有時候我們會發現有些東西並沒有按照我們預期的來工作,這裡就是一個例子。MySQL目前流行的版本預設的事務隔離級別一般是可重複讀,一般我們理解在這個隔離
InnoDB 事務隔離級別(Mysql篇)
前言: Mysql支援MyISAM和InnoDB兩種儲存引擎,區別在此就不詳細說明。此篇是講述事務,所以切記自己的table是InnDB。此處大坑! 在Mysql InnoDB 中,事務主要有四種隔離級別 Read unco
一文讀懂MySQL的事務隔離級別及MVCC機制
回顧前文: [一文學會MySQL的explain工具](https://www.cnblogs.com/itwild/p/13424113.html) [一文讀懂MySQL的索引結構及查詢優化](https://www.cnblogs.com/itwild/p/13703259.html)
mysql的事務隔離級別
too con jpg 級別 tran 開啟 數據行 修改 ges 原文地址:http://www.cnblogs.com/snsdzjlz320/p/5761387.html [Mysql]——通過例子理解事務的4種隔離級別 SQL標準定義了4種隔離級別,包括了一
mysql 不同事務隔離級別
結果 讀取 般的 lec 不同的 新增 比較 一次 基礎 repeatable read 在同一事務中,同一查詢多次進行時候,由於其他插入操作(insert)的事務提交,導致每次返回不同的結果集。 標準的repeatable read是允許幻讀的,因為這一級別只在讀取過的紀
談談MySQL的事務隔離級別
提交 執行過程 操作 dnf 情況 以及 讀取 int 並且 這篇文章能夠闡述清楚跟數據庫相關的四個概念:事務、數據庫讀現象、隔離級別、鎖機制 一、事務 先來看下百度百科對數據庫事務的定義: 作為單個邏輯單元執行一系列操作,要麽完全執行,要麽完全不執行。事務處理可以
MySQL實戰 | 03 - 誰動了我的資料:淺析MySQL的事務隔離級別
原文連結:這一次,帶你搞清楚MySQL的事務隔離級別! 使用過關係型資料庫的,應該都事務的概念有所瞭解,知道事務有 ACID 四個基本屬性:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)和永續性(Durability),今天我們主要來理解一下事務的隔離性。
遇到mysql資料庫事務隔離級別相關的小坑
幾乎所有軟體工程師都知道,mysql有4種事務隔離級別,但是實際開發過程中可能有時候忽略這個小細節,有時候可能是本來就沒有考慮過,有時候也可能是其他的原因,比如我這次踩到的小坑。 事情還原: 1、需求一:是新建一個商戶,但是客戶要求在建立商戶的時候要預設給他們開
MySQL資料庫事務隔離級別(Transaction Isolation Level)
今天在學習JDBC的時候看到了關於MySql的事務的隔離級別的問題,感覺內容挺高階的,所以記錄一篇文章,以備後面使用。 資料庫隔離級別有四種,應用《高效能mysql》一書中的說明: 然後說說修改事務隔離級別的方法: 1.全域性修改,修改mysql.in
MySQL---InnoDB引擎隔離級別詳解
#首先修改隔離級別 set tx_isolation='read-committed'; select @@tx_isolation; +----------------+ | @@tx_isolation | +----------------+ | READ-COMMITTED | +--------
innodb事務隔離級別
事務隔離級別 SQL標準定義了4類隔離級別,包括了一些具體規則,用來限定事務內外的哪些改變是可見的,哪些是不可見的。低級別的隔離級一般支援更高的併發處理,並擁有更低的系統開銷。 Read Uncommitted(讀取未提交內容) 在該隔離級別,所有事務都可以看到
Mysql中事務隔離級別與binlog_format的一點理解
之前幾年的軟體開發,總是離不開Oracle,涉及的各大專案中使用的資料庫也大多為Oracle,偶爾遇到Mysql也是簡單的使用,一直覺得Mysql很小型也很簡單,對其的理解也處於皮毛階段,最近遇到了一些Mysql的問題,對其中的事務隔離級別,以及binlog_for
【MySQL】事務隔離級別及ACID
注:begin或start transaction並不是一個事務的起點,而是在執行它們之後的第一個操作InnoDB表的語句,事務才真正開始。start transaction with consistent snapshot命令可以馬上啟動一個事務。 1、隔離級別 1.1、基本概念 讀未提交 當前事務能讀取
髒讀,不可重複度,幻讀
【1】髒讀(讀取未提交資料) 事物A讀取事物B尚未提交的資料,此時事物B發生回滾,那麼事物A讀到的資料就是髒資料,俗稱髒讀 這類情況長髮生在轉賬和取款操作中: 【2】不可重複讀(前後多
髒讀、幻讀和不可重複讀 + 事務隔離級別
1. 髒讀 :髒讀就是指當一個事務正在訪問資料,並且對資料進行了修改,而這種修改還沒有提交到資料庫中,這時,另外一個事務也訪問這個資料,然後使用了這個資料。 e.g. 1.Mary的原工資為1000, 財務人員將Mary的工資改為了8000(但未提交事務
資料庫事務隔離級別,髒讀、不可重複讀、幻讀
資料庫事務的隔離級別有4個,由低到高依次為Read uncommitted 、Read committed 、Repeatable read 、Serializable ,後面三個可以逐個解決髒讀 、不可重複讀 、幻讀 這幾類問題。 髒讀 不可重複讀 幻讀 Read u