1. 程式人生 > >sql server中高併發情況下 同時執行select和update語句死鎖問題 (二)

sql server中高併發情況下 同時執行select和update語句死鎖問題 (二)

        SQL Server死鎖使我們經常遇到的問題,資料庫操作的死鎖是不可避免的,本文並不打算討論死鎖如何產生,重點在於解決死鎖。希望對您學習SQL Server死鎖方面能有所幫助。

        死鎖對於DBA或是資料庫開發人員而言並不陌生,它的引發多種多樣,一般而言,資料庫應用的開發者在設計時都會有一定的考量進而儘量避免死鎖的產生.但有時因為一些特殊應用場景如高頻查詢,高併發查詢下由於資料庫設計的潛在問題,一些不易捕捉的死鎖可能出現從而影響業務.這裡為大家介紹由於設計問題引起的鍵查詢死鎖及相關的解決辦法.

       這裡我們在測試的同時開啟trace profiler跟蹤死鎖檢視(locks:deadlock graph).(當然也可以開啟跟蹤標記,或者應用擴充套件事件(xevents)等捕捉死鎖)

建立測試物件code

<span style="font-size:18px;"><span style="font-size:18px;">create table testklup 
( clskey int not null, 
nlskey int not null,
 cont1 int not null, 
cont2 char(3000) 
)

create unique clustered index inx_cls on testklup(clskey)

create unique nonclustered index inx_nlcs on testklup(nlskey) include(cont1)
 
insert into testklup select 1,1,100,'aaa'
insert into testklup select 2,2,200,'bbb'
insert into testklup select 3,3,300,'ccc'


</span></span>

開啟會話1 模擬高頻update操作

----模擬高頻update操作

<span style="font-size:18px;"><span style="font-size:18px;">declare @i int
set @i=100
while 1=1
 begin
 update testklup set [email protected]
 where clskey=1
 set @[email protected]+1
 end</span></span>

開啟會話2 模擬高頻select操作

----模擬高頻select操作

<span style="font-size:18px;"><span style="font-size:18px;">declare @cont2 char(3000)
while 1=1
begin
  select @cont2=cont2 from testklup where nlskey=1
end</span></span>

此時開啟會話2執行一小段時間時我們就可以看到類似錯誤資訊:圖1-1

而在我們開啟的跟蹤中捕捉到了如下的死鎖圖.圖1-2

死鎖分析:可以看出由於讀程序(108)請求寫程序(79)持有的X鎖被阻塞的同時,寫程序(79)又申請讀程序(108)鎖持有的S鎖.讀執行計劃圖1-3,寫執行計劃圖1-4

(由於在預設隔離級別下(讀提交)讀申請S鎖只是瞬間過程,讀完立即釋放,不會等待事務完成),所以在併發,執行頻率不高的情形下不易出現.但我們模擬的高頻情況使得S鎖獲得頻率非常高,此時就出現了僅僅兩個會話,一個讀,一個寫就造成了死鎖現象.


死鎖原因:讀操作中的鍵查詢造成的額外鎖(聚集索引)需求

解決方案:在瞭解了死鎖產生的原因後,解決起來就比較簡單了.

我們可以從以下幾個方面入手.

a 消除額外的鍵查詢鎖需的鎖

b 讀操作時取消獲取鎖

a.1我們可以建立覆蓋索引使select語句中的查詢列包含在指定索引中

<span style="font-size:18px;"><span style="font-size:18px;">CREATE NONCLUSTERED INDEX [inx_nlskey_incont2] ON [dbo].[testklup] ([nlskey] ASC) INCLUDE ( [cont2])</span></span>

 a.2 根據查詢需求,分步執行,通過聚集索引獲取查詢列,避免鍵查詢.

<span style="font-size:18px;"><span style="font-size:18px;">declare @cont2 char(3000) declare @clskey intwhile 1=1 begin  select @clskey=clskey from testklup where nlskey=1     select @cont2=cont2 from testklup where [email protected] end</span></span>

b 通過改變隔離級別,使用樂觀併發模式,讀操作時源行無需鎖

<span style="font-size:18px;"><span style="font-size:18px;"> declare @cont2 char(3000) 
while 1=1 
begin  

   select @cont2=cont2 from testklup with(nolock)  where nlskey=1 

end </span></span>

結束語.我們在解決問題時,最好弄清問題的本質原因,通過問題點尋找出適合自己的環境的解決方案再實施.

相關推薦

sql server中高併發情況 同時執行selectupdate語句問題

        SQL Server死鎖使我們經常遇到的問題,資料庫操作的死鎖是不可避免的,本文並不打算討論死鎖如何產生,重點在於解決死鎖。希望對您學習SQL Server死鎖方面能有所幫助。   

Linux 多執行多程序的區別小結

最近學習Linux,看到“hairetz的專欄”的帖子不錯,特轉來大家一起學習。 很想寫點關於多程序和多執行緒的東西,我確實很愛他們。但是每每想動手寫點關於他們的東西,卻總是求全心理作祟,始終動不了手。 今天終於下了決心,寫點東西,以後可以再修修補補也無妨。一.為何需要多程序(或者多執行緒),為何需

linuxI/O複用與epoll實際使用

上一節《linux下I/O複用與epoll實際使用(一)》主要講解了epoll的原理,這一節結合socket的程式設計,詳解select與epoll程式設計示例。 一、socket程式設計 在TCP/IP協議中“IP地址+TCP或者UDP埠號”唯一標識網路通訊中

執行緒之原子變數CAS演算法

上篇博文,我們介紹了多執行緒之記憶體可見性Volatile(一),但是也遺留了一個問題,如何保證變數的”原子性操作(Atomic operations)”? Volatile保證部分型別的原子性 上篇博文,我們說Voloatile不能保證原子性,有一點侷

maven打可執行jar包及依賴jar包

maven打可執行jar包,包含依賴jar包(分環境) 這篇文章打包介紹跟上一篇文章http://blog.csdn.net/u012204058/article/details/52514821

關於記憶體安全,執行緒安全,

接上,死鎖問題 1.原因 定義之前已經闡述,這裡先上一個死鎖最簡單的例子: //執行緒1: public void leftRight() { // 得到left鎖 synchronized (left) { // 得到ri

關於記憶體安全,執行緒安全,

  1.基本概念   這三樣東西知識點很多,接觸多執行緒程式設計必然接觸到,專門理一理 也算開個坑,很多細節沒有細緻解釋,後面遇到需要深挖   執行緒安全雖然處處接觸到記憶體,但跟記憶體安全還不是一回事,記憶體安全可以被定義為:不訪問任何未定義的

win環境把MySql中的資料匯入到Elasticsearch

環境問題參考我上文: 環境問題已經好了,接下來,我們講實戰。 該壓縮包幫助mysql與其他平臺連線。看到很多資源都要積分,不能選0分,所以選1分了 在bin目錄下建立jdbc.config 根據需求改連線,賬號,密碼,名字,埠等等。 input {

淺談 SQL 中的餘額問題的處理

上次模擬了 SQL 中併發執行更新餘額的語句,出現餘額負數的問題:http://blog.csdn.net/closurer/article/details/54288628 現在說說它的解決方法。 事務要正確地執行,就需要【隔離性】這個基本要素。更新餘額的語句之所以會偏離

執行多程序的區別小結

很想寫點關於多程序和多執行緒的東西,我確實很愛他們。但是每每想動手寫點關於他們的東西,卻總是求全心理作祟,始終動不了手。 今天終於下了決心,寫點東西,以後可以再修修補補也無妨。 一.為何需要多程序(或者多執行緒),為何需要併發? 這個問題或許本身都不是個問題。但是對於沒有

Win32多執行緒之DeadLock

為每一個連結串列(linked list)準備一個critical section之後(關於連結串列,請參看”“,我卻開始了另一個問題。請看下面這個用來交換兩個連結串列內容的函式: void SwapLists(List  *listA, List * listB) {  

執行緒同步與3

執行緒同步與死鎖 1、多執行緒共享資料 在多執行緒操作中,多個執行緒有可能同時處理同一個資源,這就是多執行緒中的共享資料 2、執行緒同步 解決資料共享問題必須使用同步,所謂的同步就是指多個執行緒在同一個時間段內只能有一個執行緒執行指定的程式

Objective-C高階程式設計 iOS與OS X多執行記憶體管理 讀書筆記

1.2.2 記憶體管理原則: 自己生成的物件,自己所持有 非自己生成的物件,自己也能持有 不再需要自己持有的物件時釋放 非自己持有的物件無法釋放 自己生成的物件,自己所持有 //自己生成並持有物件 id obj = [[NSObject alloc] init]; //自己持有物件   

Linux環境WEB應用啟動或關閉tomcat指令碼編寫

接下來,就是如何通過指令碼關閉tomcat: 1. 查詢程序pid 使用ps命令查詢到對應的程序,ps -aef | grep java|grep "【關鍵字】"關鍵字為應用安裝路徑,得到結果為展示當前應用pid的一條記錄 2. 將pid作為變數傳遞給下一個命令 使用sed

Java例項說明 100個執行同時向一個銀行賬戶中存入1元錢,在沒有使用同步機制使用同步機制情況執行情況

銀行賬戶類: public class Account {private double balance; // 賬戶餘額public void deposit(double money) {double newBalance = balance + money;try {T

Windows Server2012R2+SQL Server 2017 Express版本,每日自動備份數據庫的操作實踐筆記

cmd databases AS 如何 ups 執行 tom ack 近日 近日由於服務器問題,進行了一次數據庫遷移。遷移時發現SQL Server 2017 Express版本是免費的,可以滿足我的需要,就拋棄了原來的那啥版本的SQL Server 2008 r2直接使用

SQL Server 性能調優 之執行計劃Execution Plan調優

mod isp jsb see 環境 指定 logical term alt SQL Server 存在三種 Join 策略:Hash Join,Merge Join,Nested Loop Join。 Hash Join:用來處理沒有排過序/沒有索引的數據,它在內存中把

Sql Server 獲取數據庫最近執行的操作

ext 操作 desc pre light 數據 varchar sta lse select top 1000 s2.dbid, DB_NAME(s2.dbid) as [dbname], (select top 1 substring(s2.text,sta

SQL Server沒有足夠的記憶體繼續執行程式

  有一個表的資料特別大,我點選生成指令碼的時候,喜歡新建視窗,但是不行,資料量太大了,所以選擇儲存檔案,儲存到本地了。然後我點選執行,又報沒有記憶體去執行。。。還是因為資料量太大了   解決辦法,使用sqlcmd命令即可 調出命令列工具,輸入 sqlcmd

sql server記憶體使用情況 檢視Sql Server 資料庫的記憶體使用情況

檢視Sql Server 資料庫的記憶體使用情況 轉自:https://www.cnblogs.com/wanghao4023030/p/8299478.html  -- 查詢SqlServer總體的記憶體使用情況 se