国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

Transaction And Lock--READ COMMITTED隔離級別下的"臟讀"

2024-07-21 02:49:59
字體:
來源:轉載
供稿:網友
Transaction And Lock--READ COMMITTED隔離級別下的"臟讀"

在READ UNCOMMITTED事務隔離級別下或使用WITH(NOLOCK)來查詢數據時,會出現臟讀情況,因此對于一些比較"關鍵"的業務,會要求不能使用WITH(NOLOCK)或允許在READ UNCOMMITTED事務隔離級別下,于是我們使用默認的READ COMMITTED隔離級別來訪問數據,但是這樣真的就沒有問題么?

讓我們來做個小實驗

準備測試數據

--=======================================--創建測試表CREATE TABLE TB106(    C0 INT IDENTITY(1,1) PRIMARY KEY,    C1 INT,    C2 CHAR(100),    C3 NVARCHAR(4000))GO--=======================================--創建一個非聚簇索引CREATE INDEX IX_C1_C2ON TB106(C1,C2)GO--=======================================--向表中填充1000條數據DECLARE @ID INT SET @ID=0WHILE(@ID<1000)BEGININSERT INTO TB106(C1,C2,C3)SELECT @ID,@ID,REPLICATE('A',3800)SET @ID=@ID+1ENDGO--=================================--查看表中數據,共1000行SELECT * FROM TB106

開啟回話1,運行以下腳本

--======================--開啟事務,更新C0為100的數據BEGIN  TRANUPDATE TB106SET C1=101WHERE C0=100

開啟回話2,運行以下腳本

--=======================--查詢數據SELECT C1,C2,C0 FROM TB106

我們會發現回話2被回話1阻塞,但是已經有少量數據開始被讀取

我們再次回到回話1,繼續執行以下腳本

--=====================--更新C0為5的數據,并提交事務UPDATE TB106SET C1=1000WHERE C0=5COMMIT

伴隨著回話1事務的提交,回話2沒有了阻塞,順利完成查詢,但是奇跡出現了

表中只有1000行數據,為什么我們能查出1001行數據來呢?

我們來分析下執行結果,不難發現c0=5的數據被讀取了兩遍,更新前后的數據都被讀取到,這不科學!在c0=5的數據被更新前,數據被讀取了一遍,然后當讀到c0=100的時候,回話被阻塞,然后c0=5的數據被更新,更新后的數據記錄存放位置變動,移到了索引尾部,當阻塞結束后,該記錄又再次被讀取,從而導致一行記錄被讀取兩遍。

--=====================================================================

這并不是MS的bug,讓我們來仔細閱讀下各種隔離級別的解釋:

READ UNCOMMITTED 指定語句可以讀取已由其他事務修改但尚未提交的行。 在 READ UNCOMMITTED 級別運行的事務,不會發出共享鎖來防止其他事務修改當前事務讀取的數據。READ UNCOMMITTED 事務也不會被排他鎖阻塞,排他鎖會禁止當前事務讀取其他事務已修改但尚未提交的行。設置此選項之后,可以讀取未提交的修改,這種讀取稱為臟讀。在事務結束之前,可以更改數據中的值,行也可以出現在數據集中或從數據集中消失。該選項的作用與在事務內所有 SELECT 語句中的所有表上設置 NOLOCK 相同。這是隔離級別中限制最少的級別。

READ COMMITTED 指定語句不能讀取已由其他事務修改但尚未提交的數據。這樣可以避免臟讀。其他事務可以在當前事務的各個語句之間更改數據,從而產生不可重復讀取和幻像數據。該選項是 SQL Server 的默認設置。

REPEATABLE READ 指定語句不能讀取已由其他事務修改但尚未提交的行,并且指定,其他任何事務都不能在當前事務完成之前修改由當前事務讀取的數據。 對事務中的每個語句所讀取的全部數據都設置了共享鎖,并且該共享鎖一直保持到事務完成為止。這樣可以防止其他事務修改當前事務讀取的任何行。其他事務可以插入與當前事務所發出語句的搜索條件相匹配的新行。如果當前事務隨后重試執行該語句,它會檢索新行,從而產生幻讀。由于共享鎖一直保持到事務結束,而不是在每個語句結束時釋放,所以并發級別低于默認的 READ COMMITTED 隔離級別。此選項只在必要時使用。

--=====================================================================

誤區:不知道有多少朋友和我一樣,錯誤認為REPEATABLE READ分離級別只是為了保證兩次SQL查詢的數據不發生變化,而忽略了在一次查詢期間內數據發生變化導致的問題。而由于導致該問題的發生概率比較低,往往不能引起我們足夠重視,從而錯誤地認為READ COMMITTED隔離級別可以勝任類似需求。

--======================================================================

依舊是妹子壓貼


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 建瓯市| 延津县| 磐安县| 措美县| 普兰店市| 樟树市| 天柱县| 浮梁县| 汉源县| 伊吾县| 盘山县| 贺兰县| 福海县| 彰化县| 宝鸡市| 华容县| 双鸭山市| 莱州市| 余干县| 奉贤区| 民勤县| 潼南县| 洛阳市| 板桥市| 林周县| 密云县| 莒南县| 砚山县| 容城县| 云霄县| 常州市| 建德市| 百色市| 峨山| 科尔| 鄂托克前旗| 宜州市| 尖扎县| 通道| 云阳县| 肇东市|