資料庫並發死鎖
⑴ 死鎖怎麼回事
一、活鎖
如果事務T1封鎖了數據R,事務T2又請求封鎖R,於是T2等待。T3也請求封鎖R,當T1釋放了R上的封鎖之後系統首先批准了T3的請求,T2仍然等待。然後T4又請求封鎖R,當T3釋放了R上的封鎖之後系統又批准了T4的請求,...,T2有可能永遠等待,這就是活鎖的情形,如圖8.4(a)所示。
避免活鎖的簡單方法是採用先來先服務的策略。
二、死鎖
如果事務T1封鎖了數據R1,T2封鎖了數據R2,然後T1又請求封鎖R2,因T2已封鎖了R2,於是T1等待T2釋放R2上的鎖。接著T2又申請封鎖R1,因T1已封鎖了R1,T2也只能等待T1釋放R1上的鎖。這樣就出現了T1在等待T2,而T2又在等待T1的局面,T1和T2兩個事務永遠不能結束,形成死鎖。
1.
死鎖的預防
在資料庫中,產生死鎖的原因是兩個或多個事務都已封鎖了一些數據對象,然後又都請求對已為其他事務封鎖的數據對象加鎖,從而出現死等待。防止死鎖的發生其實就是要破壞產生死鎖的條件。預防死鎖通常有兩種方法:
①
一次封鎖法
一次封鎖法要求每個事務必須一次將所有要使用的數據全部加鎖,否則就不能繼續執行。
一次封鎖法雖然可以有效地防止死鎖的發生,但也存在問題,一次就將以後要用到的全部數據加鎖,勢必擴大了封鎖的范圍,從而降低了系統的並發度。
②
順序封鎖法
順序封鎖法是預先對數據對象規定一個封鎖順序,所有事務都按這個順序實行封鎖。
順序封鎖法可以有效地防止死鎖,但也同樣存在問題。事務的封鎖請求可以隨著事務的執行而動態地決定,很難事先確定每一個事務要封鎖哪些對象,因此也就很難按規定的順序去施加封鎖。
可見,在操作系統中廣為採用的預防死鎖的策略並不很適合資料庫的特點,因此DBMS在解決死鎖的問題上普遍採用的是診斷並解除死鎖的方法。
2.
死鎖的診斷與解除
①
超時法
如果一個事務的等待時間超過了規定的時限,就認為發生了死鎖。超時法實現簡單,但其不足也很明顯。一是有可能誤判死鎖,事務因為其他原因使等待時間超過時限,系統會誤認為發生了死鎖。二是時限若設置得太長,死鎖發生後不能及時發現。
②
等待圖法
事務等待圖是一個有向圖G=(T,U)。
T為結點的集合,每個結點表示正運行的事務;U為邊的集合,每條邊表示事務等待的情況。若T1等待T2,則T1、T2之間劃一條有向邊,從T1指向T2。事務等待圖動態地反映了所有事務的等待情況。並發控制子系統周期性地(比如每隔1分鍾)檢測事務等待圖,如果發現圖中存在迴路,則表示系統中出現了死鎖。
DBMS的並發控制子系統一旦檢測到系統中存在死鎖,就要設法解除。通常採用的方法是選擇一個處理死鎖代價最小的事務,將其撤消,釋放此事務持有的所有的鎖,使其它事務得以繼續運行下去。當然,對撤消的事務所執行的數據修改操作必須加以恢復。
⑵ net高並發實時系統,應該用什麼辦法來解決資料庫死鎖
從然間機理角度講,鎖死的原因肯定有兩把鎖,各自進程所了不同的資源,進行操作,而又試圖訪問對方資源,由於訪問對方資源時,對方鎖定資源只能等待,如果雙方都一直等待,就會造成死鎖。因此看,死鎖問題並不一定只發生在資料庫中,也可能有線程死鎖。
對於資料庫死鎖,一般資料庫本身都有犧牲機制,可以放棄一個操作,因此倒是好處理一些,只要能夠捕獲到異常並能夠處理即可,但由於很多應用開發商結構化做的不很好,往往是沒有很好處理異常,才會導致軟體的大量問題。對於新手,往往連警告都不帶看的,更甭提異常的預防處理了。
另外一點是,很多人編程很不注意,往往將begintransaction放到交互的開始中,交互完成時再committransaction, 而不是完成處理時設置事務,其他鏈接不死才怪,這只能說是人禍,不能怪資料庫。
倒是線程死鎖需要編程時手工處理,很多人往往沒有怎麼注意它。
⑶ 詳解MySQL(InnoDB)如何處理死鎖
鎖是需要事務結束後才釋放的。
一個是 MVCC,一個是兩階段鎖協議。
為什麼要並發控制呢?是因為多個用戶同時操作 MySQL 的時候,為了提高並發性能並且要求如同多個用戶的請求過來之後如同串列執行的一樣(為了解決臟讀、不可重復讀、幻讀)
官方定義:
兩階段鎖協議是指所有事務必須分兩個階段對數據加鎖和解鎖,在對任何數據進行讀、寫操作之前,事務首先要獲得對該數據的封鎖;在釋放一個封鎖之後,事務不再申請和獲得任何其他封鎖。
對應到 MySQL 上分為兩個階段:
但是兩階段鎖協議不要求事務必須一次將所有需要使用的數據加鎖(innodb在需要的索引列數據才鎖行),並且在加鎖階段沒有順序要求,所以這種並發控制方式會形成死鎖。
MySQL有兩種死鎖處理方式:
死鎖檢測 (默認開啟)
死鎖檢測的原理是構建一個以事務為頂點、鎖為邊的有向圖,判斷有向圖是否存在環,存在即有死鎖。
回滾
檢測到死鎖之後,選擇插入更新或者刪除的行數最少的事務回滾,基於 INFORMATION_SCHEMA.INNODB_TRX 表中的 trx_weight 欄位來判斷。
收集死鎖信息:
減少死鎖:
死鎖解決:
⑷ 資料庫為什麼總是產生死鎖
多線程是很容易造成死鎖,一般情況下死鎖都是因為並發操作引起的。我不懂JAVA,但死鎖這個問題每種開發工具和資料庫都會碰到.解決辦法是:
1、程序方面優化演算法(如有序資源分配法、銀行演算法等),在一個程序里,能不用多線程更新同一張資料庫表 盡量不要用,如果要用,其避免死鎖的演算法就很復雜。
2、資料庫方面設置等待超時時間
3、發生死鎖後直接KILL掉資料庫進程
⑸ 資料庫死鎖,並發問題
補充樓主:
其實我沒什麼經驗,只不過是了解一些基礎的東西罷了。
一樓的 一朵瘩紅花 實際經驗很豐富,你可以向她咨詢一下。
你問的問題挺好得。三個概念緊密聯系在一起。
這樣說吧:並發的幾個事務同時發生,不加鎖控制的話數據就會亂套了,而加了鎖後,又是並發訪問會出現死鎖,所以就會出現避免死鎖的一些措施。
首先談並發:理論指的是在一段時間同時對某件事進行操作。 注意精度問題,修改資料庫是在一段時間內操作,不是在某個時刻,而日誌則會從 時刻 開始記錄你的操作。
造成死鎖的原因是為了防止 不同的用戶同時間(不是時刻)都對某個數據修改,造成訪問不一致的問題。
比如你讀了資料庫的一個數據然後把它修改了並存回去,是需要時間的(假如是student表中的有個grade屬性,你改了一條記錄的一個值)在這個過程當中,有人又訪問了資料庫並且恰恰訪問的是存回去之前的數據,然後他要進行操作,過了一段時間,此時你已經存回去了數據。會發現原來的數據被改動了。這時數據就亂套了。(專業術語叫讀臟數據,其實還有很多其他類似這種導致前後數據不一致的問題)所以為了限定這種操作,資料庫設計了-----鎖---來鎖定這種操作。就是你正在操作某個數據的時候----通常之前會先鎖定這個數據,這樣別人就不能對此數據操作了(嚴格來說就是只能讀,不能改),必須等你操作完才能對此數據修改等操作,這就在一定程度上避免了前後操作數據不一致的問題。
但是有了鎖後,新問題出現了,就是死鎖:
簡單解釋死鎖:進程A等待進程B釋放他的資源,B又等待A釋放他的資源,這樣就互相等待就形成死鎖
官方解釋死鎖
死鎖,根本原因在於對共享存儲區的訪問。在資料庫中也一樣,如果需要「修改」一條數據,首先資料庫管理系統會在上面加鎖,以保證在同一時間只有一個事務能進行修改操作。鎖有多種實現方式,比如意向鎖,共享-排他鎖,鎖表,樹形協議,時間戳協議等等。鎖還有多種粒度,比如可以在表上加鎖,也可以在記錄上加鎖。
在並發控制中,鎖是非常重要的。
至於在Oracle還是別的資料庫管理系統中,死鎖產生的原因沒有不同,不同的頂多是鎖的實現或者死鎖的恢復等罷了
再來說說事務:
事務簡單來說就是 一系列的對資料庫的操作揉在一起,要麼同時完成,要麼就都不完成。
比如---你要取錢的過程就可以當成是一個小的事務: 插卡,輸入取錢金額,取走錢,拿出來卡。此過程缺一不可。把所有這些過程細節封裝起來就成為一個事務。
以oracle資料庫為例:
一個事務(你可以認為是一系列業務的操作)起始於dml語句(insert、update、delete)
即一條dml語句就做為一個事務的起始,然後根據業務需要,進行其他的dml操作都算是事務的一部分。
最後碰到commit。或者rollback,或者其他意外什麼的都算作一個事務的結束。
整個過程就是一個事務。
事務的理論解釋就是那四個什麼特性:什麼原子性、一致性、隔離性和持久性
簡稱ACID
剩下的:資料庫是建立在操作系統之上的一個層次。
你問的是資料庫的存儲機制??工作機制??還是什麼的??
資料庫就是存數據的。資料庫管理系統是 對存的數據進行高效率的管理
大的結構分物理數據跟邏輯數據。
物理數據就是數據在存儲設備上的存儲方式,什麼物理聯系,物理結構,物理記錄等 術語。
邏輯數據就是程序員和用戶看到的數據形式。什麼邏輯聯系,邏輯結構==同上
資料庫管理類系統就是把這些邏輯跟物理相互轉換。 好比你輸入的叫邏輯數據存儲在磁碟上叫物理數據。等等。
廢話了一堆,也不知道回答對你的問題沒~~
⑹ 資料庫的並發操作可能帶來哪些問題 丟失更新 死鎖 違反唯一性約束
資料庫中常見的並發操作所帶來的一致性問題包括:丟失的修改、不可重復讀、讀臟數據、幻影讀(幻影讀在一些資料中往往與不可重復讀歸為一類)。
丟失修改
下面先來看一個例子,說明並發操作帶來的數據的不一致性問題。
考慮飛機訂票系統中的一個活動序列:
甲售票點(甲事務)讀出某航班的機票余額A,設A=16.
乙售票點(乙事務)讀出同一航班的機票余額A,也為16.
甲售票點賣出一張機票,修改余額A←A-1.所以A為15,把A寫回資料庫.
乙售票點也賣出一張機票,修改余額A←A-1.所以A為15,把A寫回資料庫.
結果明明賣出兩張機票,資料庫中機票余額只減少1。
歸納起來就是:兩個事務T1和T2讀入同一數據並修改,T2提交的結果破壞了T1提交的結果,導致T1的修改被丟失。前文(2.1.4數據刪除與更新)中提到的問題及解決辦法往往是針對此類並發問題的。但仍然有幾類問題通過上面的方法解決不了,那就是:
不可重復讀
不可重復讀是指事務T1讀取數據後,事務T2執行更新操作,使T1無法再現前一次讀取結果。具體地講,不可重復讀包括三種情況:
事務T1讀取某一數據後,事務T2對其做了修改,當事務1再次讀該數據時,得到與前一次不同的值。例如,T1讀取B=100進行運算,T2讀取同一數據B,對其進行修改後將B=200寫回資料庫。T1為了對讀取值校對重讀B,B已為200,與第一次讀取值不一致。
事務T1按一定條件從資料庫中讀取了某些數據記錄後,事務T2刪除了其中部分記錄,當T1再次按相同條件讀取數據時,發現某些記錄神密地消失了。
事務T1按一定條件從資料庫中讀取某些數據記錄後,事務T2插入了一些記錄,當T1再次按相同條件讀取數據時,發現多了一些記錄。(這也叫做幻影讀)
讀"臟"數據
讀"臟"數據是指事務T1修改某一數據,並將其寫回磁碟,事務T2讀取同一數據後,T1由於某種原因被撤消,這時T1已修改過的數據恢復原值,T2讀到的數據就與資料庫中的數據不一致,則T2讀到的數據就為"臟"數據,即不正確的數據。
產生上述三類數據不一致性的主要原因是並發操作破壞了事務的隔離性。並發控制就是要用正確的方式調度並發操作,使一個用戶事務的執行不受其它事務的干擾,從而避免造成數據的不一致性。
並發一致性問題的解決辦法
封鎖(Locking)
封鎖是實現並發控制的一個非常重要的技術。所謂封鎖就是事務T在對某個數據對象例如表
⑺ 資料庫死鎖的死鎖原因
一般情況只發生鎖超時,就是一個進程需要訪問資料庫表或者欄位的時候,另外一個程序正在執行帶鎖的訪問(比如修改數據),那麼這個進程就會等待,當等了很久鎖還沒有解除的話就會鎖超時,報告一個系統錯誤,拒絕執行相應的SQL操作。
發生死鎖的情況比較少,比如一個進程需要訪問兩個資源(資料庫表或者欄位),當獲取一個資源的時候進程就對它執行鎖定,然後等待下一個資源空閑,這時候如果另外一個進程也需要兩個資源,而已經獲得並鎖定了第二個資源,那麼就會死鎖,因為當前進程鎖定第一個資源等待第二個資源,而另外一個進程鎖定了第二個資源等待第一個資源,兩個進程都永遠得不到滿足。
資料庫死鎖的解決方案。
死鎖的預防和解除:
理解了死鎖的原因,尤其是產生死鎖的四個必要條件,就可以最大可能地避免、預防和解除死鎖。所以,在系統設計、進程調度等方面注意如何不讓這四個必要條件成立,如何確定資源的合理分配演算法,避免進程永久占據系統資源。此外,也要防止進程在處於等待狀態的情況下佔用資源,在系統運行過程中,對進程發出的每一個系統能夠滿足的資源申請進行動態檢查,並根據檢查結果決定是否分配資源,若分配後系統可能發生死鎖,則不予分配,否則予以分配 。因此,對資源的分配要給予合理的規劃。
如何將死鎖減至最少
雖然不能完全避免死鎖,但可以使死鎖的數量減至最少。將死鎖減至最少可以增加事務的吞吐量並減少系統開銷,因為只有很少的事務回滾,而回滾會取消事務執行的所有工作。由於死鎖時回滾而由應用程序重新提交。
下列方法有助於最大限度地降低死鎖:
(1)按同一順序訪問對象。
(2)避免事務中的用戶交互。
(3)保持事務簡短並在一個批處理中。
(4)使用低隔離級別。
(5)使用綁定連接。
按同一順序訪問對象
如果所有並發事務按同一順序訪問對象,則發生死鎖的可能性會降低。例如,如果兩個並發事務獲得 Supplier 表上的鎖,然後獲得 Part 表上的鎖,則在其中一個事務完成之前,另一個事務被阻塞在 Supplier 表上。第一個事務提交或回滾後,第二個事務繼續進行。不發生死鎖。將存儲過程用於所有的數據修改可以標准化訪問對象的順序。
避免事務中的用戶交互
避免編寫包含用戶交互的事務,因為運行沒有用戶交互的批處理的速度要遠遠快於用戶手動響應查詢的速度,例如答復應用程序請求參數的提示。例如,如果事務正在等待用戶輸入,而用戶去吃午餐了或者甚至回家過周末了,則用戶將此事務掛起使之不能完成。這樣將降低系統的吞吐量,因為事務持有的任何鎖只有在事務提交或回滾時才會釋放。即使不出現死鎖的情況,訪問同一資源的其它事務也會被阻塞,等待該事務完成。
保持事務簡短並在一個批處理中
在同一資料庫中並發執行多個需要長時間運行的事務時通常發生死鎖。事務運行時間越長,其持有排它鎖或更新鎖的時間也就越長,從而堵塞了其它活動並可能導致死鎖。
保持事務在一個批處理中,可以最小化事務的網路通信往返量,減少完成事務可能的延遲並釋放鎖。
使用低隔離級別
確定事務是否能在更低的隔離級別上運行。執行提交讀允許事務讀取另一個事務已讀取(未修改)的數據,而不必等待第一個事務完成。使用較低的隔離級別(例如提交讀)而不使用較高的隔離級別(例如可串列讀)可以縮短持有共享鎖的時間,從而降低了鎖定爭奪。
使用綁定連接
使用綁定連接使同一應用程序所打開的兩個或多個連接可以相互合作。次級連接所獲得的任何鎖可以象由主連接獲得的鎖那樣持有,反之亦然,因此不會相互阻塞。
⑻ 什麼是資料庫死鎖
死鎖,根本原因在於對共享存儲區的訪問。在資料庫中也一樣,如果需要「修改」一條數據,首先資料庫管理系統會在上面加鎖,以保證在同一時間只有一個事務能進行修改操作。鎖有多種實現方式,比如意向鎖,共享-排他鎖,鎖表,樹形協議,時間戳協議等等。鎖還有多種粒度,比如可以在表上加鎖,也可以在記錄上加鎖。
在並發控制中,鎖是非常重要的。
至於在Oracle還是別的資料庫管理系統中,死鎖產生的原因沒有不同,不同的頂多是鎖的實現或者死鎖的恢復等罷了
⑼ redis並發set會死鎖嗎
會。Redis是一個開源的使用ANSIC語言編寫、支持網路、可基於內存亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API。redis並發set會死鎖,從2010年3月15日起,Redis的開發工作由VMware主持。從2013年5月開始,Redis的開發由Pivotal贊助。
⑽ 如何解決多線程造成的資料庫死鎖
多線程是很容易造成死鎖,一般情況下死鎖都是因為並發操作引起的。我不懂JAVA,但死鎖這個問題每種開發工具和資料庫都會碰到.解決辦法是:
1、程序方面優化演算法(如有序資源分配法、銀行演算法等),在一個程序里,能不用多線程更新同一張資料庫表
盡量不要用,如果要用,其避免死鎖的演算法就很復雜。
2、資料庫方面設置等待超時時間
3、發生死鎖後直接KILL掉資料庫進程