網站首頁 編程語言 正文
什么是數據庫死鎖
在操作系統領域當中,死鎖指的是兩個或者兩個以上的進程在運行的過程中,因為爭奪共同的訪問資源而相互等待阻塞,最終造成阻礙進程繼續執行的一種阻塞現象。那么在數據庫領域當中死鎖又是怎樣的表現形式呢?
如下圖所示,假設事務A持有行1的共享鎖,事務B持有行2的共享鎖,那么此時事務A請求持有行2的排他鎖,那么在事務B釋放資源之前都處于阻塞等待的狀態,同樣的事務B請求持有行1的排他鎖,在事務A 釋放資源之前同樣也是處于阻塞等待的狀態。也就是說事務 B 完成之后事務 A 才能完成,而事務A的完成又依賴于事務B的完成,這就形成了循環依賴的問題,最終導致死鎖情況的發生。
如何確定死鎖位置
//先確定數據庫有沒有死鎖情況發生
select * from pg_stat_activity where datname = 'product_db';
//查詢可能鎖了的表的oid
select oid from pg_class where relname='product';
//查詢對應的pid
select pid from pg_locks where relation='oid' //上面查詢出來的oid
//取消或者終止對應的進程
select pg_cancel_backend(pid);
select pg_terminate_backend(pid);
死鎖的可能原因以及解決辦法
以上分析了PostgreSQL出現死鎖后如何定位分析,那么接下來就需要總結分析分析下數據庫出現死鎖情況的原因以及一般的應對解決辦法。
1、索引使用問題導致的死鎖問題
索引使用存在問題的話會導致死鎖問題,假設在一個數據查詢的事務當中,進行數據檢索的時候沒辦法按照SQL中的where條件進行查詢,因此導致了全表掃描,那么此時數據庫表的行級鎖會上升為表級鎖。如果此時有多個未能按照where條件進行數據查詢的事務存在,那么就容易導致數據庫死鎖問題。也就是說在數據庫表數據量比較大的時候,對應進行數據查詢的表沒有建立索引或者說索引創建的不合理導致無法通過索引進行數據查詢,只能通過全表索引,這樣的場景下就容易產生死鎖。
如何避免:
在進行數據查詢的時候,對應的SQL語句不宜太過復雜,也就是說盡量避免多張表的關聯查詢。
2、不同事務之間的訪問順序問題
當用戶A 訪問數據庫表A時,此時對表A加了共享鎖,然后又訪問數據庫表B。而此時另一個用戶B 訪問表B,對表B加了共享鎖,然后試圖訪問表A。但是用戶A由于用戶B已經鎖住表B,它必須等待用戶B釋放表B才能繼續,同樣用戶B要等用戶A釋放表A才能繼續,也就是說互相等待對方釋放資源,從而導致了死鎖的發生。
如何避免:
這種情況在實際項目中遇到的可能比較多,主要還是需要通過控制代碼的執行邏輯,避免多表操作時同時鎖住多個資源。
避免死鎖的實戰建議
(1)如果平臺中存在大事務,盡量將其拆分為小事務。因為大事務一般操作的數據庫表或者數據都比較多,因此造成死鎖或者阻塞的概率就會相對較大。
(2)為數據庫表設計合理的索引,盡量避免數據查詢時索引未覆蓋或者索引失效的情況,因為全表掃描會會導致給表中的數據行上鎖,大大增加了數據庫產生死鎖的概率。
(3)如果業務允許,我們可以嘗試將隔離級別調低,比如將隔離級別從RR調整為RC,可以避免掉很多因為gap鎖造成的死鎖。
補充:下面在看下Postgresql死鎖的處理
背景:
對表進行所有操作都卡住,原因可能是更新表時導致這個表死鎖了,開始進行排查
解決一:查詢pg_stat_activity有沒有記錄
pg版本10.2
select pid,query,* from pg_stat_activity where datname='死鎖的數據庫' and wait_event_type = 'Lock';
select pg_cancel_backend('死鎖那條數據的pid值');##只能殺死select 語句, 對其他語句不生效
pg_terminate_backend('死鎖那條數據的pid值');#select,drop等各種操作
執行后發現select和delete表時正常執行,但truncate和drop表時會一直運行,也不報錯。
“drop table” 和 “truncate table” 需要申請排它鎖"ACCESS EXCLUSIVE", 執行這個命令卡住時,說明此時這張表上還有操作正在進行,比如查詢等,
那么只有等待這個查詢操作完成,“drop table” 或"truncate table"或者增加字段的SQL才能獲取這張表上的 "ACCESS EXCLUSIVE"鎖,操作才能進行下去。
解決二:查詢pg_locks是否有這個對象的鎖
select oid,relname from pg_class where relname='table name';
select locktype,pid,relation,mode,granted,* from pg_locks where relation= '上面查詢出來的oid';
select pg_terminate_backend('進程ID');
問題解決!!!
坑:一開始不知道pg_cancel_backend(‘死鎖那條數據的pid值');##只能殺死select 語句, 對其他語句不生效,殺了進程查詢發現還存在,反復殺反復存在,換了pg_terminate_backend(‘進程ID')問題就解決了。
PS:postgresql表死鎖問題的排查方式
1.查詢激活的執行中的sql,查看有哪些更新update的sql。
select *
from pg_stat_activity
where state = 'active';
2. 查詢表中存在的鎖
select a.locktype, a.database, a.pid, a.mode, a.relation, b.relname
from pg_locks a
join pg_class b on a.relation = b.oid
where lower(b.relname) = 'h5_game';
3. 殺掉死鎖進程
select pg_terminate_backend(pid)
from pg_stat_activity
where state = 'active'
and pid != pg_backend_pid()
--and pid = 14172
and pid in (select a.pid
from pg_locks a
join pg_class b on a.relation = b.oid
where lower(b.relname) = 'news_content')
鎖模式
/* NoLock is not a lock mode, but a flag value meaning "don't get a lock" */
#define NoLock 0
#define AccessShareLock 1 /* SELECT */
#define RowShareLock 2 /* SELECT FOR UPDATE/FOR SHARE */
#define RowExclusiveLock 3 /* INSERT, UPDATE, DELETE */
#define ShareUpdateExclusiveLock 4 /* VACUUM (non-FULL),ANALYZE, CREATE
* INDEX CONCURRENTLY */
#define ShareLock 5 /* CREATE INDEX (WITHOUT CONCURRENTLY) */
#define ShareRowExclusiveLock 6 /* like EXCLUSIVE MODE, but allows ROW
* SHARE */
#define ExclusiveLock 7 /* blocks ROW SHARE/SELECT...FOR
* UPDATE */
#define AccessExclusiveLock 8 /* ALTER TABLE, DROP TABLE, VACUUM
* FULL, and unqualified LOCK TABLE */
原文鏈接:https://blog.csdn.net/Diamond_Tao/article/details/124567168
相關推薦
- 2022-04-25 Entity?Framework?Core中執行SQL語句和存儲過程的方法介紹_實用技巧
- 2024-04-06 Linux如何清理Redis中的緩存
- 2022-06-29 Oracle中的常用函數詳解_oracle
- 2022-08-27 Pycharm遠程連接服務器跑代碼的實現_python
- 2023-01-04 C++無try-catch的異常捕獲示例詳解_C 語言
- 2022-02-05 lxml提取html標簽內容, tostring()不能顯示中文 解決方案
- 2023-04-26 C語言實現數組元素排序方法詳解_C 語言
- 2023-02-05 Python實現前向和反向自動微分的示例代碼_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支