1. 程式人生 > >select查詢造成的資料庫死鎖

select查詢造成的資料庫死鎖



    最近給一個客戶更新了一個模組,查詢過程中老是出現查詢結果不一致的情況,有時多有時少,通過除錯發現sql語句都一樣,返回的結果卻不一樣,跟蹤SQL語句發現,在查詢結果少的時候,會報 事務被作為犧牲品的死鎖錯誤,正常情況下,如果報錯會返回null值,為什麼會出現一部分資料,難道是髒讀?(關於這個髒讀的問題到現在都沒明白怎麼回事。

   事情過了幾天,情況也不是很嚴重,就一直沒管他,後來一個老開發過來,在說到這一塊問題的時候,他說可能是我排序的問題,我的資料排序是在程式中完成的,當時為了優化SQL效能,把sql的order by 語句都通過程式進行排序了,排序程式碼如下,

於是就把程式排序遮蔽掉,把排序加到SQL語句裡面去執行,結果出來的結果要麼是0 要麼是全部結果,結果為0行時同樣報死鎖錯誤,因為有其它專案要忙,這個問題又擱置了幾天。

 /// <summary>
        ///  對DataTable進行排序
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="SortCols"></param>
        /// <returns></returns>
        public DataTable SortTable(DataTable dt, string SortCols)
        {
            if (dt == null)
            {
                return null;
            }
            if (dt.Rows.Count == 0)
            {
                return dt;
            }
            DataTable dtSort = new DataTable();
            dtSort = dt.Clone();
            DataRow[] RowArr = dt.Select(" 1=1", SortCols);
            foreach (DataRow row in RowArr)
            {
                dtSort.Rows.Add(row.ItemArray);
            }
            return dtSort;
        }

       週一的時候,由於客戶的操作資料特別多,這種情況越來越嚴重,直接影響到了客戶的正常工作,沒辦法,老闆下命令一定要把這一塊搞好,於是開始在百度上各種搜尋,我是搞程式的,對資料庫還算了解,因為沒有DBA,這些資料庫維護工作只能自己做,通過sql profiler提取記錄,發現所有死鎖基本上發生在這條語句和一個儲存過程上,我儲存過程是執行的n條sql語句,當時這樣做而沒有用事務去做的原因,是考慮到如果客戶機突然斷網,事務不會提交,就會造成阻塞或死鎖,所以就把要執行的語句傳入一個儲存過程,讓儲存過程來執行,不知道這種做法對不對,我感覺應該會好點,儲存過程如下,從昨天晚上一直在研究這個跟蹤記錄,發現有一個現象 在儲存過程執行到插入A表時,這個時候另外一個查詢的SQL語句可以執行,但是死鎖往往是發生在這個時候,查詢語句是對A表的關聯查詢,A表中有兩個索引一個聚集索引,一個非聚集索引。昨天查了一天無果,上午開始考慮如果做讀寫分離這種問題是不是不會再發生,上午測試了一下SQL的複製功能,雖然延遲在秒級別,但效果還不是太理想,把情況給老闆大致說了一下,老闆的意思還是找出來死鎖的原因,下午又查了一下午,剛開始懷疑是不是A表資料太大了(5000多萬行),在插入的時候消耗過大引起的,後來用DBCC ShowContig掃描了一下 密度達到了99%多,於是開始懷疑是填充因子的問題,是不是太大了,導致插入的時候分頁,後來想想我的聚集索引是加在時間上的,而時間列是用getdate()獲取的預設值,不應該消耗太大,於是就先把A表清出去了一部分,準備明天再看結果。

      臨睡覺前準備再看下跟蹤語句,發現所有的死鎖都是發生在上述所產的A表插入上和那個select語句上,於是開始搜尋select 造成的死鎖,查到了下面引用的這篇文章,發現裡面講述的和我這個狀況非常相似,A表上的兩個索引造成的死鎖

儲存過程執行插入時要用到A表的聚集索引的X鎖,插入完成之後會更新A表的非聚集索引

查詢的語句中由於查詢列不包含在索引中 所以先使用了A表的非聚集索引 又請求A表的聚集索引查詢不包含的欄位

這樣就發生了互斥,造成了死鎖,文中給出了兩種解決方法

一個是索引覆蓋(把查詢的輸出列include現在的索引裡面)  這種方法感覺不可行 不可能把這麼多列加到索引裡面
二種方法 是用SQL Server行隔離級別控制   明天測試一下這個方法 只要對其它業務流程不影響  就用這種方法

就到這了 洗洗睡了 希望對你們有幫助

ALTER PROCEDURE [dbo].[ExcuteTrans]
(
@SqlArr varchar(8000)
)
 AS


declare @nSql nvarchar(4000)
declare  @error int
declare  @rtnerror int

set @[email protected]
set @error=0
set @rtnerror=0
set @nSql=Replace(@nSql,'#',' set @[email protected]@[email protected] ')
set @[email protected]+' set @[email protected]@[email protected] select @[email protected]'

begin tran

exec sp_executesql @nSql ,N'@rtnerror int  out,@error int',@rtnerror out,@error

if(@rtnerror>0)
 begin 
 rollback tran
 return 
end

commit tran





參考文章:sql server中高併發情況下 同時執行select和update語句死鎖問題 (一)

相關推薦

程式設計面試題:編寫一個會造成資料庫的應用

相信對於"開發一個會產生死鎖的Java應用”這類需求,大家都能順利完成。但是如果題目要求得更具體一些,要求這個死鎖發生在資料庫層面,應該怎樣完成呢? 下面我提供一種答案,採用SAP的程式語言ABAP(Advanced Business Application Programming)實現。 我們從ABAP幫

select查詢造成資料庫

     最近給一個客戶更新了一個模組,查詢過程中老是出現查詢結果不一致的情況,有時多有時少,通過除錯發現sql語句都一樣,返回的結果卻不一樣,跟蹤SQL語句發現,在查詢結果少的時候,會報 事務被作為犧牲品的死鎖錯誤,正常情況下,如果報錯會返回null值,為什麼會出現一

頻繁更新基礎資料表造成資料庫

       最近,有個比較大的專案出現數據庫死鎖。經過分析資料庫trace檔案,發現死鎖的是基礎資料表疾病診斷。根據對應的sql語句找到了問題所在,門診醫生錄入診斷時,程式裡面同時去更新疾病診斷基礎

【Java TCP/IP Socket】深入剖析socket——TCP通信中由於底層隊列填滿而造成問題(含代碼)

parameter 兩個 因此 tar 機制 至少 基礎 named 測試 基礎準備 首先需要明白數據傳輸的底層實現機制,在http://blog.csdn.net/ns_code/article/details/15813809這篇博客中有詳細的介紹,在上面的博

select for update引發分析

而在 back ons 關系 級別 分析 得到 ica 分享 本文針對MySQL中在Repeatable Read的隔離級別下使用select for update可能引發的死鎖問題進行分析。 1. 案例 業務中需要對各種類型的實體進行編號,例如對於x類實體的編號可能是x2

使用 jstack 查詢線程錯誤日誌

inf sta jstack ack 進入 img grep alt bubuko 進入系統 使用 grep -n ‘java.lang.Thread.State:BLOCKED‘ jstack.log -A5; 查詢: 使用 jstack 查詢線程死鎖錯誤日誌

關於在專案中遇到MySQL資料庫的問題

在MySQL中, 當一個事務去更新某條資料, 還沒有提交的時候, 第二個事務去更新該資料, 則會出現等待獲取鎖超時異常: >>  Lock wait timeout exceeded; try restarting transaction 此異

資料庫_荔枝_解決方法

轉自高效能mysql;   【1.3.2】死鎖 1)死鎖定義:指兩個或多個事務在同一資源上相互佔用, 並請求鎖定對方佔用的資源,從而導致惡性迴圈的現象; 當多個事務試圖以不同順序鎖定資源時,就可能產生死鎖;多個事務同時鎖定同一個資源時,也會產生死鎖; 2)死鎖解決方法

MySQL資料庫原因及解決

      資料庫和作業系統一樣,是一個多使用者使用的共享資源。當多個使用者併發地存取資料 時,在資料庫中就會產生多個事務同時存取同一資料的情況。若對併發操作不加控制就可能會讀取和儲存不正確的資料,破壞資料庫的一致性。加鎖是實現資料庫並 發控制的一個非常重要的技術。在實

關於oracle資料庫的解決 以及產生的原因

前段時間寫sql語句事物造成了資料庫死鎖,導致所有更新操作無法執行 1.查死鎖 檢視關於鎖的會話資訊 select * from v$session t1, v$locked_object t2 where t1.sid = t2.SESSION_ID   &nb

利用opensips實現freeswitch負載均衡的資料庫問題

多個freeswitch實現負載均衡,要使用同一個資料庫,這樣每個freeswitch都要建立到資料庫的連線,在每個呼叫結束時,都要到資料庫中刪除一些資料,比如要到calls表刪除呼叫資訊,如果多個freeswitch同時進行刪除操作,有可能會產生死鎖,比如: 2018-0

MySQL 5.7.25資料庫

1、檢視innodb狀態 show engine innodb status\G 2、開啟lock_monitor監控 use databases sys; create table innodb_lock_monitor(x int) engine=innodb; 3、查詢程序 m

資料庫及解決方法

死鎖的概念:   死鎖是指兩個或者兩個以上的事務在執行過程中,因爭奪鎖資源而造成的一種互相等待的現象。 死鎖的處理機制:  解決死鎖最有用最簡單的方法是不要有等待,將任何等待都轉化為回滾,並且事務重新開始。但是有可能影響併發效能。 1:超時回滾,即當兩個事務互相等待時,

K3cloud中查詢導致系統的程序以及sql語句

DECLARE @spid INTDECLARE @blk INTDECLARE @count INTDECLARE @index INTDECLARE @lock TINYINT SET @lock=0 CREATE TABLE #temp_who_lock(id INT IDENTITY(1, 1),

K3cloud中查詢導致系統的進程以及sql語句

ast sql print 沒有 tiny 語法 processes code sts DECLARE @spid INTDECLARE @blk INTDECLARE @count INTDECLARE @index INTDECLARE @lock TINYINT SE

資料庫導致分佈事務中大批量更新資料庫不成功

1 問題描述 未簽收的訂單十五天之後自動簽收:總共2個步驟: step1 在樂購系統中批量更新未簽收訂單的狀態,step2: 通過RPC修改訂單系統的訂單狀態, step1和step2放到一個事務中。然後發現step2 訂單DB狀態修改成功,但是step1 樂購db的訂單狀態並未修改。 2 排查過程 懷疑是

減少SQLServer資料庫的技巧

如果兩個使用者程序分別鎖定了不同的資源,接著又試圖鎖定對方所鎖定的資源,就會產生死鎖。此時,SQL Server將自動地選擇並中止其中一個程序以解除死鎖,使得另外一個程序能夠繼續處理。系統將回退被中止的事務,並向被回退事務的使用者傳送錯誤資訊。    大多數設計良好的應用都會

資料庫的檢查和解決方法

資料庫死鎖的檢查方法一、         資料庫死鎖的現象程式在執行的過程中,點選確定或儲存按鈕,程式沒有響應,也沒有出現報錯。二、         死鎖的原理當對於資料庫某個表的某一列做更新或刪除等操作,執行完畢後該條語句不提交,另一條對於這一列資料做更新操作的語句在執行的

資料庫原因及解決辦法

死鎖(Deadlock) 所謂死鎖:是指兩個或兩個以上的程序在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的程序稱為死鎖程序。由於資源佔用是互斥的,當某個程序提出申請

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

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