資料庫鎖表的分析與解決(三)
遇到一個多事務併發的問題
mysql資料庫鎖
推薦圈子: Pipboy
更多相關推薦 對鎖機制的研究要具備兩個條件:
1.資料量大
2.多個使用者同時併發
如果缺少這兩個條件,資料庫不容易產生死鎖問題。研究起來可能會事倍功半。如果這兩個條件都有,但你還是按資料庫預設設定來處理資料,則會帶來很多的問題,比如:
1)丟失更新
A,B兩個使用者讀同一資料並進行修改,其中一個使用者的修改結果破壞了另一個修改的結果
2)髒讀
A使用者修改了資料時,B使用者也在讀該資料,但A使用者因為某些原因取消了對資料的修改,資料恢復原值,此時B得到的資料就與資料庫內的資料產生了不一致
3)不可重複讀
B使用者讀出該資料並修改,同時,A使用者也在讀取資料,此時A使用者再讀取資料時發現前後兩次的值不一致
SQL SERVER 作為多使用者資料庫系統,以事務為單位,使用鎖來實現併發控制。SQLSERVER使用“鎖”確保事務完整性和資料一致性。
一、鎖的概念
鎖(LOCKING)是最常用的併發控制機構。是防止其他事務訪問指定的資源控制、實現併發控制的一種主要手段。鎖是事務對某個資料庫中的資源(如表和記錄)存取前,先向系統提出請求,封鎖該資源,事務獲得鎖後,即取得對資料的控制權,在事務釋放它的鎖之前,其他事務不能更新此資料。當事務撤消後,釋放被鎖定的資源。
當一個使用者鎖住資料庫中的某個物件時,其他使用者就不能再訪問該物件
二、鎖的粒度
SQL Server 2000 具有多粒度鎖定,允許一個事務鎖定不同型別的的資源。為了使鎖定的成本減至最少,SQL Server 自動將資源鎖定在適合任務的級別。鎖定在較小的粒度(例如行)可以增加併發但需要較大的開銷,因為如果鎖定了許多行,則需要控制更多的鎖。鎖定在較大的粒度(例如表)就併發而言是相當昂貴的,因為鎖定整個表限制了其它事務對錶中任意部分進行訪問,但要求的開銷較低,因為需要維護的鎖較少。SQL Server 可以鎖定行、頁、擴充套件盤區、表、庫等資源。
資源 級別 描述
RID 行鎖 表中的單個行
Key 行級鎖 索引中的行
Page 頁級鎖 一個數據頁或者索引頁
Extent 頁級鎖 一組資料頁或者索引頁
Table 表級鎖 整個表
Database 資料庫級鎖 整個資料庫
選擇多大的粒度,根據對資料的操作而定。如果是更新表中所有的行,則用表級鎖;如果是更新表中的某一行,則用行級鎖。
行級鎖是一種最優鎖,因為行級鎖不可能出現數據既被佔用又沒有使用的浪費現象。但是,如果使用者事務中頻繁對某個表中的多條記錄操作,將導致對該表的許多記錄行都加上了行級鎖,資料庫系統中鎖的數目會急劇增加,這樣就加重了系統負荷,影響系統性能。因此,在SQL Server中,還支援鎖升級(lock escalation)。
所謂鎖升級是指調整鎖的粒度,將多個低粒度的鎖替換成少數的更高粒度的鎖,以此來降低系統負荷。在SQL Server中當一個事務中的鎖較多,達到鎖升級門限時,系統自動將行級鎖和頁面鎖升級為表級鎖。
特別值得注意的是,在SQL Server中,鎖的升級門限以及鎖升級是由系統自動來確定的,不需要使用者設定。
三、鎖的模式
鎖模式以及描述表
鎖模式 描述
共享(S) 用於不更改或不更新資料(只讀操作),如SELECT語句
更新(U) 用於可更新的資源中。防止當多個會話在讀取、鎖定以及隨後可能進行的資源更新時發生常見形式的死鎖。
排它(X) 用於資料修改操作,例如 INSERT、UPDATE或DELETE。確保不會同時對同一資源進行多重更新
意向 當 Microsoft SQL Server 資料庫引擎獲取低級別的鎖時,它還將在包含更低級別物件的物件上放置意向鎖.例如: 當鎖定行或索引鍵範圍時,資料庫引擎將在包含行或鍵的頁上放置意向鎖。當鎖定頁時,資料庫引擎將在包含頁的更高級別的物件上放置意向鎖。
意向鎖的型別為:意向共享(IS)、意向排它(IX)以及意向排它共享(SIX)
架構 在執行依賴於表架構的操作時使用。架構鎖的型別為:架構修改(Sch-M)和架構穩定(Sch-S)
大容量更新(BU) 向表中大容量複製資料並指定了TABLOCK提示時使用
四 SQL Server 中鎖的設定
1 處理死鎖和設定死鎖優先順序
死鎖就是多個使用者申請不同封鎖,由於申請者均擁有一部分封鎖權而又等待其他使用者擁有的部分封鎖而引起的無休止的等待
可以使用SET DEADLOCK_PRIORITY控制在發生死鎖情況時會話的反應方式。
Syntax:
SET DEADLOCK_PRIORITY { LOW | NORMAL}
其中LOW說明該程序會話的優先順序較低,在出現死鎖時,可以首先中斷該程序的事務。
2 處理超時和設定鎖超時持續時間。
@@LOCK_TIMEOUT 返回當前會話的當前鎖超時設定,單位為毫秒
SET LOCK_TIMEOUT 設定允許應用程式設定語句等待阻塞資源的最長時間。當語句等待的時間大於 LOCK_TIMEOUT 設定時,系統將自動取消阻塞的語句,並給應用程式返回"已超過了鎖請求超時時段"的 1222 號錯誤資訊
示例
1)將鎖超時期限設定為 1,800 毫秒。
SET LOCK_TIMEOUT 1800
2) 配置索引的鎖定粒度
可以使用 sp_indexoption 系統儲存過程來設定用於索引的鎖定粒度
3)設定事務隔離級別
SET TRANSACTION ISOLATION LEVEL
五 檢視鎖的資訊
1 執行 EXEC SP_LOCK 報告有關鎖的資訊
2 查詢分析器中按Ctrl+2可以看到鎖的資訊
六、奇怪的sql語句
Java程式碼
begin tran
update titles set title_idid=title_id where 1=2
if (selectavg(price)fromtitles)>$15
begin
update titles set price=price*1.10
where price<(select avg(price)from titles)
end
commit tran
begin tran
update titles set title_idid=title_id where 1=2
if (selectavg(price)fromtitles)>$15
begin
update titles set price=price*1.10
where price<(select avg(price)from titles)
end
commit tran
update titles set title_idid=title_id where 1=2,這個條件是永遠也不會成立的,如此寫的含義是什麼呢?
這裡的where子句看起來很奇怪,儘管計算出的結果總是false。當優化器處理此查詢時,因為它找不到任何有效的SARG,它的查詢規劃就會強制使用一個獨佔鎖定來進行表掃描。此事務執行時,where子句立即得到一個false值,於是不會執行實際上的掃描,但此程序仍得到了一個獨佔的表鎖定。
因為此程序現在已有一個獨佔的表鎖,所以可以保證沒有其他事務會修改任何資料行,能進行重複讀,且避免了由於holdlock所引起的潛在性死鎖。
但是,在使用表鎖定來儘可能地減少死鎖的同時,也增加了對錶鎖定的爭用。因此,在實現這種方法之前,你需要權衡一下:避免死鎖是否比允許併發地對錶進行訪問更重要。
所以,在這個事務中,沒有其他程序修改表中任何行的price。
七 如何避免死鎖
1 使用事務時,儘量縮短事務的邏輯處理過程,及早提交或回滾事務;
2 設定死鎖超時引數為合理範圍,如:3分鐘-10分種;超過時間,自動放棄本次操作,避免程序懸掛;
3 所有的SP都要有錯誤處理(通過@error)
4 一般不要修改SQL SERVER事務的預設級別。不推薦強行加鎖
5 優化程式,檢查並避免死鎖現象出現;
1)合理安排表訪問順序
2)在事務中儘量避免使用者干預,儘量使一個事務處理的任務少些。
3)採用髒讀技術。髒讀由於不對被訪問的表加鎖,而避免了鎖衝突。在客戶機/伺服器應用環境中,有些事務往往不允許讀髒資料,但在特定的條件下,我們可以用髒讀。
4)資料訪問時域離散法。資料訪問時域離散法是指在客戶機/伺服器結構中,採取各種控制手段控制對資料庫或資料庫中的物件訪問時間段。主要通過以下方式實現: 合理安排後臺事務的執行時間,採用工作流對後臺事務進行統一管理。工作流在管理任務時,一方面限制同一類任務的執行緒數(往往限制為1個),防止資源過多佔用; 另一方面合理安排不同任務執行時序、時間,儘量避免多個後臺任務同時執行,另外,避免在前臺交易高峰時間執行後臺任務
5)資料儲存空間離散法。資料儲存空間離散法是指採取各種手段,將邏輯上在一個表中的資料分散到若干離散的空間上去,以便改善對錶的訪問效能。主要通過以下方法實現: 第一,將大表按行或列分解為若干小表; 第二,按不同的使用者群分解。
6)使用盡可能低的隔離性級別。隔離性級別是指為保證資料庫資料的完整性和一致性而使多使用者事務隔離的程度,SQL92定義了4種隔離性級別:未提交讀、提交讀、可重複讀和可序列。如果選擇過高的隔離性級別,如可序列,雖然系統可以因實現更好隔離性而更大程度上保證資料的完整性和一致性,但各事務間衝突而死鎖的機會大大增加,大大影響了系統性能。
7)使用Bound Connections。Bound connections 允許兩個或多個事務連線共享事務和鎖,而且任何一個事務連線要申請鎖如同另外一個事務要申請鎖一樣,因此可以允許這些事務共享資料而不會有加鎖的衝突。
8)考慮使用樂觀鎖定或使事務首先獲得一個獨佔鎖定。
八如何對行、 表、資料庫加鎖
1 如何鎖一個表的某一行
Java程式碼
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT * FROM table1 ROWLOCK WHERE A = 'a1'
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT * FROM table1 ROWLOCK WHERE A = 'a1'
2 鎖定資料庫的一個表
select col1 from 表 (tablockx) where 1=1 ;
加鎖後其它人不可操作,直到加鎖使用者解鎖,用commit或rollback解鎖
3.例項
建表
Java程式碼
create table table1(A varchar(50) not null, B varchar(50) ,C varchar(50));
create table table2(D varchar(50),E varchar(50))
insert table1 (A,B,C) values(‘a1’,’b1’,’c1’);
insert table1 (A,B,C) values(‘a2’,’b2’,’c2’);
insert table1 (A,B,C) values(‘a3’,’b3’,’c3’);
insert table2 (D,E) values(‘d1’,’e1’);
insert table2 (D,E) values(‘d2’,’e2’);
create table table1(A varchar(50) not null, B varchar(50) ,C varchar(50));
create table table2(D varchar(50),E varchar(50))
insert table1 (A,B,C) values(‘a1’,’b1’,’c1’);
insert table1 (A,B,C) values(‘a2’,’b2’,’c2’);
insert table1 (A,B,C) values(‘a3’,’b3’,’c3’);
insert table2 (D,E) values(‘d1’,’e1’);
insert table2 (D,E) values(‘d2’,’e2’);
1)排它鎖
Java程式碼
-- A事務先更新table1表,在更新時,對其他事務進行排他
begin tran
update table1 set A='aa' where B='b2';
waitfor delay '00:00:30'; --等待30秒
commit tran
-- A事務先更新table2表
begin tran
select * from table1 where B='b2';
commit tran
-- A事務先更新table1表,在更新時,對其他事務進行排他
begin tran
update table1 set A='aa' where B='b2';
waitfor delay '00:00:30'; --等待30秒
commit tran
-- A事務先更新table2表
begin tran
select * from table1 where B='b2';
commit tran若同時執行上述兩個事務,則select查詢必須等待update執行完畢才能執行即要等待30秒
2)共享鎖
Java程式碼
-- A事務先查詢table1表,在查詢時,加共享鎖,防止其他事務對該表進行修改操作
begin tran
select * from table1 holdlock where B='b2' ;
-holdlock人為加鎖
waitfor delay '00:00:30';--等待30秒
commit tran
-- A事務先查詢table1表,後更改table1表
begin tran
select A,C from table1 where B='b2';
update table1 set A='aa' where B='b2';
commit tran
-- A事務先查詢table1表,在查詢時,加共享鎖,防止其他事務對該表進行修改操作
begin tran
select * from table1 holdlock where B='b2' ;
-holdlock人為加鎖
waitfor delay '00:00:30';--等待30秒
commit tran
-- A事務先查詢table1表,後更改table1表
begin tran
select A,C from table1 where B='b2';
update table1 set A='aa' where B='b2';
commit tran若併發執行上述兩個事務,則B事務中的select查詢可以執行,而update必須等待第一個事務釋放共享鎖轉為排它鎖後才能執行即要等待30秒
3)死鎖
Java程式碼
-- A事務先更新table1表,然後延時30秒,再更新table2表;
begin tran
update table1 set A='aa' where B='b2';
--這將在 Table1 中生成排他行鎖,直到事務完成後才會釋放該鎖。
waitfor delay '00:00:30';
--進入延時
update table2 set D='d5' where E='e1' ;
commit tran
-- B事務先更新table2表,然後延時10秒,再更新table1表;
begin tran
update table2 set D='d5' where E='e1';
--這將在 Table2 中生成排他行鎖,直到事務完成後才會釋放該鎖
waitfor delay '00:00:10'
--進入延時
update table1 set A='aa' where B='b2' ;
commit tran
-- A事務先更新table1表,然後延時30秒,再更新table2表;
begin tran
update table1 set A='aa' where B='b2';
--這將在 Table1 中生成排他行鎖,直到事務完成後才會釋放該鎖。
waitfor delay '00:00:30';
--進入延時
相關推薦
資料庫鎖表的分析與解決(三)
ORACLE裡幾種鎖模式 遇到一個多事務併發的問題 mysql資料庫鎖 推薦圈子: Pipboy 更多相關推薦 對鎖機制的研究要具備兩個條件: 1.資料量大 2.多個使用者同時併發 如果缺少這兩個條件,資料庫不容易產生死鎖問題。研究起來可能會事倍功半。如果這兩個條件都有,但
mysql慢查詢原因分析與解決(三)——索引及查詢優化
索引的型別 Ø 普通索引:這是最基本的索引型別,沒唯一性之類的限制。 Ø 唯一性索引:和普通索引基本相同,但所有的索引列值保持唯一性。 Ø 主鍵:主鍵是一種唯一索引,但必須指定為”PRIMARY KEY”。 Ø 全文索引:MYSQL從3.23.23開始支援全
資料庫鎖表的分析與解決(二)
SQL Server的鎖機制一. 為什麼要引入鎖 多個使用者同時對資料庫的併發操作時會帶來以下資料不一致的問題: 丟失更新 A,B兩個使用者讀同一資料並進行修改,其中一個使用者的修改結果破壞了另一個修改的結果,比如訂票系統 髒讀 A使用者修改了資料,隨後B使用者又讀出該資料
SQL註入漏洞的分析與利用(三)
和數 form 打開 用戶 data 用戶名 text 必須 存儲 MySQL數據庫: 元數據庫information_schema1.在5.0以後版本的MySQL中存在著一個元數據庫information_schema,其中存儲著用戶在MySQL中創建的所有其他數據庫的信
python進階之資料分析與展示(三)
資料分析之表示 資料存取與函式 資料的CSV檔案存取 CSV (Comma‐Separated Value, 逗號分隔值) CSV是一種常見的檔案格式,用來儲存批量資料。 np.savetxt(frame, array, fmt=’%.
redis原始碼分析與思考(三)——字典中鍵的兩種hash演算法
在Redis字典中,得到鍵的hash值顯得尤為重要,因為這個不僅關乎到是否字典能做到負載均衡,以及在效能上優勢是否突出,一個良好的hash演算法在此時就能發揮出巨大的作用。而一個良好的has
SQL Server索引進階第十一篇:索引碎片分析與解決(上)
索引設計是資料庫設計中比較重要的一個環節,對資料庫的效能其中至關重要的作用,但是索引的設計卻又不是那麼容易的事情,效能也不是那麼輕易就獲取到的,很多的技術人員因為不恰當的建立索引,最後使得其效果適得其反,可以說“成也索引,敗也索引”。 相關有關索引碎片的問題,大家應該是聽過不少,也許也很多的朋友
資料結構與演算法(三)-線性表之靜態連結串列
前言:前面介紹的線性表的順序儲存結構和鏈式儲存結構中,都有對物件地引用或指向,也就是程式語言中有引用或者指標,那麼在沒有引用或指標的語言中,該怎麼實現這個的資料結構呢? 一、簡介 定義:用陣列代替指標或引用來描述單鏈表,即用陣列描述的連結串列叫做靜態連結串列,這種描述方法叫做遊標實現法;
資料庫中介軟體 Sharding-JDBC 原始碼分析 —— SQL 解析(三)之查詢SQL
������關注微信公眾號:【芋艿的後端小屋】有福利: 1. RocketMQ / MyCAT / Sharding-JDBC 所有原始碼分析文章列表 2. RocketMQ / MyCAT / Sharding-JDBC 中文註釋原始碼
資料庫鎖表原因及解決思路
1、鎖表發生在insert update 、delete 中 2、鎖表的原理是 資料庫使用獨佔式封鎖機制,當執行上面的語句時,對錶進行鎖住,直到發生commite 或者 回滾 或者退出資料庫使用者 3、鎖表的原因 第一、 A程式執行了對 tableA 的 in
《Redis設計與實現》[第二部分]單機資料庫的實現-C原始碼閱讀(三)
3、AOF持久化 關鍵字:AOF持久化:檔案寫入與同步,AOF檔案重寫,資料一致性 與RDB持久化通過儲存資料庫中的鍵值對來記錄資料庫狀態不同,AOF持久化是通過儲存redis伺服器所執行的寫命令來記錄資料庫狀態的 被寫入AOF檔案的所有命令都是以
oracle入門之對表數據查詢(三)
取值 無法 排除 avg 臨時表 多表 單行 pan 相同 oracle表復雜查詢--子查詢 什麽是子查詢? 子查詢是指嵌入在其它sql語句中的select語句,也叫嵌套查詢。 單行子查詢 單行子查詢是指只返回一行數據的子查詢語句。 請思考:如果顯示與smith同一部門
MySQL與Oracle(三)---日期對比(Oracle)
數據庫 alt to_date pan 技術分享 時間日期 軟件 floor lte Oracle: 1.獲取當前日期的年,月,日,時,分,秒 select to_char(sysdate,‘yyyy‘) as nowYear from dual; //獲取時間
WPF入門教程系列八——布局之Grid與UniformGrid(三)
input 接下來 toolbar wid ids 全部 ica tar 生成 五. Grid Grid顧名思義就是“網格”,它的子控件被放在一個一個實現定義好的小格子裏面,整齊配列。 Grid和其他各個Panel比較起來,功能最多也最為復雜。要使用Grid,首先要向Row
Java中String、StringBuilder、StringBuffer常用源碼分析及比較(三):String、StringBuilder、StringBuffer比較
val str 成員變量 相同 += let .get end art 看這篇隨筆之前請務必先看前面兩章: Java中String、StringBuilder、StringBuffer常用源碼分析及比較(一):String源碼分析 Java中String、StringBui
【轉載】TCP粘包問題分析和解決(全)
刪除 而且 實例 報文 底層 nagle 存在 ngxin 想想 TCP通信粘包問題分析和解決(全) 在socket網絡程序中,TCP和UDP分別是面向連接和非面向連接的。因此TCP的socket編程,收發兩端(客戶端和服務器端)都要有成對的socket,因此,發送端為了將
SQL註入漏洞的分析與利用(一)
ces mysql 得出 必須 排序 快速搭建 oracle 學習筆記 min SQL註入的核心思想 黑客在正常的需要調用數據庫的URL後面構造一段數據庫查詢代碼,然後根據返回的結果,從而獲得想要的某些數據。SQL結構化查詢語言,絕大多數關系型數據庫(MySQL、Acces
SQL註入漏洞的分析與利用(二)
manage 如果 得到 nio 學習筆記 sql註入 .com 密碼 vpd Access手工註入 1.實驗環境:實驗平臺:小旋風ASPWeb服務器目標網站:南方數據2.02.打開網站,隨意點開一個頁面看到?id=4說明有參數傳遞,用的是get方法,可能是一個註入點加入判
Redis 設計與實現 (三)
check 就會 鍵值 鍵值對 是否 second 變化 write 次數 RDB 持久化 一、生成RDB cmd:SAVE --阻塞進程,執行完,才能有效接收客戶端命令。 cmd: BGSAVE --非阻塞,開啟子進程保存。 客
Kotlin學習與實踐 (三)fun 函數
意義 element 中間 類的方法 int prefix cal save tor 通過例子來學習如何高效的在Kotlin中定義使用函數。 1、命名參數、默認參數、頂層函數、擴展函數 * 展示幾種創建集合類的方法和擴展的簡單操作集合類的方法 fun createColl