數據庫是一個多用戶使用的共享資源,當多個用戶併發地存取數據時,在數據庫中就會產生多個事務同時存取同一數據的情況。若對併發操作不加控制就可能會讀取和存儲不正確的數據,破壞數據庫的一致性。加鎖是實現數據庫併發控制的一個非常重要的技術。在實際應用中經常會遇到的與鎖相關的異常情況,當兩個事務需要一組有衝突的鎖,而不能將事務繼續下去的話,就會出現死鎖,嚴重影響應用的正常執行。
鎖類型:
1、共享鎖(Share Locks,即S鎖):加了共享鎖的數據對象可以被其他事務讀取,但不能修改。數據庫利用這兩種基本的鎖類型來對數據庫的事務進行併發控制。
2、排它鎖(Exclusive Locks,即X鎖):當數據對象被加上排它鎖時,其他的事務不能對它讀取和修改。
3、獨佔鎖:在共享鎖的基礎上,升級爲獨佔鎖。
4、更新鎖:所有用戶都可以讀,但我將來可能會做更新操作,我已經獲取了從共享鎖(用來讀)到排他鎖(用來更新)的資格。一個事物只能有一個更新鎖獲此資格。
出現原因:
1、事務之間對資源訪問順序的交替:一個用戶1 訪問表A(鎖住了表A),然後又訪問表B;另一個用戶2 訪問表B(鎖住了表B),然後企圖訪問表A;這時用戶1由於用戶2已經鎖住表B,它必須等待用戶2釋放表B才能繼續,同樣用戶2要等用戶1釋放表A才能繼續,這就死鎖就產生了。 解決方案:程序邏輯問題、注意表的調用順序
2、併發修改同一記錄:用戶1查詢一條紀錄,然後修改該條紀錄;這時用戶2修改該條紀錄,這時用戶1的事務裏鎖的性質由查詢的共享鎖企圖上升到獨佔鎖,而用戶2裏的獨佔鎖由於1有共享鎖存在所以必須等1釋放掉共享鎖,而1由於2的獨佔鎖而無法上升的獨佔鎖也就不可能釋放共享鎖,於是出現了死鎖 :
3、索引不當導致全表掃描:事務執行了一條不滿足條件的語句執行了全表掃描或表數據量非常大索引建的過少或不合適的時候
解決方案:SQL語句中不要使用太複雜的關聯多表的查詢並建索引進行優化
注:
1、oracle 查看死鎖並釋放死鎖
select sess.sid, sess.serial#, lo.oracle_username, lo.os_user_name, ao.object_name, lo.locked_mode from v$locked_object lo, dba_objects ao, v$session sess where ao.object_id = lo.object_id and lo.session_id = sess.sid;
alter system kill session '738,1429'; --釋放資源
2、mysql 查看死鎖並釋放死鎖
show processlist --查看數據庫中各個進程的運行狀態
select * from information_schema.innodb_trx ---查詢正在運行的事務
kill id
詳情參考:oracle 索引全面解析