greenplum在執行vacuum和insert產生死鎖問題定位及解決方案

来源:http://www.cnblogs.com/qiannianyuan/archive/2017/11/27/greenplum.html
-Advertisement-
Play Games

首先聲明:未經本人同意,請勿轉載,謝謝! 本人使用自己編譯的開源版本的greenplum資料庫用於學習,版本為PostgreSQL 8.3.23 (Greenplum Database 4.3.99.00 build dev) on x86_64-unknown-linux-gnu, compile ...


首先聲明:未經本人同意,請勿轉載,謝謝!

 

本人使用自己編譯的開源版本的greenplum資料庫用於學習,版本為PostgreSQL 8.3.23 (Greenplum Database 4.3.99.00 build dev) on x86_64-unknown-linux-gnu, compiled by GCC gcc (GCC) 4.8.5 20150623

在使用的過程中遇到不少的問題,今天記錄一下高併發的情況下,執行insert和vacuum操作造成的死鎖,以及解決方案

 

一、問題描述:

在對ao分區表進行高併發測試的時候同時執行了vacuum的動作,發現會有死鎖的問題產生,可以通過如下手段復現:

1)多個線程迴圈執行insert into t3 select * from XX(t3為本例中用於測試的分區表),為了提高問題復現的速度,可以僅對錶中的一個分區進行操作

2)單個線程迴圈執行vacuum的動作

一段時間後會發現vacuum和insert都卡住,至此問題被覆現出來。

 

二、結論:

該問題僅在AO分區表中會出現,產生的原因是由於資料庫加鎖的流程設計不合理導致(詳情見分析過程)。

 

三、問題定位及解決方案

拋磚引玉,僅分享自己知道的一點點東西,如果有錯誤的地方還請指正,歡迎大家一起來討論這個問題。

 

1)首先連接master執行:

select * from pg_stat_activity;

查到如下結果:

(圖一)

發現有一個session是lock狀態,為了弄清楚這裡的lock的具體情況,則連接master和standby查看鎖的具體情況,執行如下sql:

 

select a.locktype,b.relname,substring(c.current_query,1,50),c.xact_start,a.pid,a.mode,a.granted from pg_locks a,pg_class b,pg_stat_activity c
 where a.relation = b.oid and a.pid = c.procpid and relname like 't3%';

 

master:

 (圖二)

segment1:

(圖三)

segment2:

(圖四)

需要註意的是,這裡圖三和圖四中在pg_stat_activity表中的current_query一列有<IDLE> in transaction,這裡的值和我們平時看到的<IDLE>不是一回事,並不是一個空閑的連接,要弄清楚它的意義來看下官方文檔:

(圖五)

官方的文檔里,對該值僅有這麼一小段描述,這裡並不能完全的表達出這個欄位的意思,我們來看源碼:

(圖六)

源碼里就可以看出這種狀態說明該連接的事務是處於阻塞狀態。

那麼又是為什麼會有鎖等待的出現呢,因為同一時間,針對同一個對象,有些鎖是不能夠同時被不同的事務所持有的,如果一個事務持有了某個鎖,另一個事務需要獲取相同的鎖或者是與這個鎖衝突的鎖,就會出現等待的情況,我們來看下鎖之間的衝突情況:

 (圖七)

綜合以上的所有信息,畫出瞭如下的圖:

(圖七)

說明:

相同顏色的色塊表示同一個連接(在物理機上,由ps -ef | grep $pid查到的con確定),紅色的線表示等待關係。

由上圖可以清晰的看出,在master上,con52等待con49持有的鎖,而在segment2中,con49等待con52持有的鎖,因此產生了死鎖。 那麼又是什麼造成了這種鎖的狀態的形成?官方的描述中AccessShareLock僅僅是在對錶數據不產生任何影響的查詢語句才會申請:   (圖八) 這裡看圖七的master節點,明明產生的是AccessShareLock,與官方的描述出現了不一致,對於這個疑惑,只有源碼能告訴我們答案: (圖九) 這裡有個if條件,這說明在處理ao分區表的時候,會在處理完成後會在master上加上AccessShareLock,結合圖七和圖九,也就解釋了為什麼在master會產生insert的鎖等待vacuum的情況了,同時也回答了為什麼結論中說該問題僅會出現在ao分區表中。 至此,產生這個問題的原因基本明晰了,那麼遇到了這種情況該如何解決? 要知道不同的鎖之間誰等待了誰,提供如下sql,很方便的就能知道等待關係:
create or replace function f_lock_level(i_mode text) returns integer as $$
begin
  RETURN  (select case i_mode
    when 'INVALID' then 0
    when 'AccessShareLock' then 1
    when 'RowShareLock' then 2
    when 'RowExclusiveLock' then 3
    when 'ShareUpdateExclusiveLock' then 4
    when 'ShareLock' then 5
    when 'ShareRowExclusiveLock' then 6
    when 'ExclusiveLock' then 7
    when 'AccessExclusiveLock' then 8
    else 0
  end );
end;
$$ language plpgsql strict;

--查詢
with t_wait as                     
(select a.mode,a.locktype,a.database,a.relation,a.page,a.tuple,a.classid,a.objid,a.objsubid,
a.pid,a.virtualtransaction,a.virtualxid,a,transactionid,b.current_query,b.xact_start,b.query_start,
b.usename,b.datname from pg_locks a,pg_stat_activity b where a.pid=b.procpid and not a.granted),
t_run as
(select a.mode,a.locktype,a.database,a.relation,a.page,a.tuple,a.classid,a.objid,a.objsubid,
a.pid,a.virtualtransaction,a.virtualxid,a,transactionid,b.current_query,b.xact_start,b.query_start,
b.usename,b.datname from pg_locks a,pg_stat_activity b where a.pid=b.procpid and a.granted)
select r.locktype,r.mode r_mode,r.usename r_user,r.datname r_db,r.relation::regclass,r.pid r_pid,
r.page r_page,r.tuple r_tuple,r.xact_start r_xact_start,r.query_start r_query_start,
now()-r.query_start r_locktime,r.current_query r_query,w.mode w_mode,w.pid w_pid,w.page w_page,
w.tuple w_tuple,w.xact_start w_xact_start,w.query_start w_query_start,
now()-w.query_start w_locktime,w.current_query w_query  
from t_wait w,t_run r where
  r.locktype is not distinct from w.locktype and
  r.database is not distinct from w.database and
  r.relation is not distinct from w.relation and
  r.page is not distinct from w.page and
  r.tuple is not distinct from w.tuple and
  r.classid is not distinct from w.classid and
  r.objid is not distinct from w.objid and
  r.objsubid is not distinct from w.objsubid and
  r.transactionid is not distinct from w.transactionid and
  r.pid <> w.pid
  order by f_lock_level(w.mode)+f_lock_level(r.mode) desc,r.xact_start;

註意:上面的sql適用於文章開頭部分greenplum內核版本,不同的版本會有些許差異,這個sql是我根據文章最後參考資料德哥給出的SQL自己修改的,如果您的環境中無法運行,請使用德哥給出的語句。

 

該sql會返回類似如下的結果(部分):

(圖十)

每條結果以w_開頭的結果表示正在等待的會話信息,以r_開頭的代表正在運行的會話信息。 為了不影響正常的插入流程,可以找到vacuum語句的pid,使用select pg_terminate_backend($pid);語句終止vacuum的會話,業務即可繼續進行。   那麼問題是不是就此可以結束?其實並沒有,我們來看官方文檔: 官方指出,在發生死鎖的情況下,會自動的回滾一個事務,保證另一個事務的正常運行,那麼在上面所述的情況下,為什麼沒有發生事務的自動回滾?這是我一直沒有想明白的問題,如果有相關的專業人士看到這篇文章請指點一二,解答我心中的疑問,感激不盡!   參考資料: https://yq.aliyun.com/articles/86631 https://github.com/greenplum-db/gpdb/pull/425
https://github.com/greenplum-db/gpdb/issues/2837 在github中,有提出使用debug的方式復現死鎖的問題,這是最快捷的方式,同時也給出了源碼級別的修複建議,感興趣的朋友可以自行閱讀。   結語: 本人一直做的是java的開發工作,C並不是特別熟悉,要解決這個問題,根本上還得從源碼入手,本人沒有這個能力,如果有朋友知道如何修複這個問題,還請告知。同時本文如有表述不對的地方,還請各位指出,我會加強自身的學習,保證分享出來的東西是正確的。 另外,推薦一個好朋友的公眾號,我覺得裡面文章特別好,很多問題是真正講清楚了,全都是他自己一點點整理出來的,我一直在讀他的文章,受益良多。

 

   
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 蘋果在 iOS 11 的發佈會上,推出了兩種新的媒體格式 `HEVC`,都是為了保證畫質的情況下,大大減少視頻、照片的大小。 一、簡介 全稱 High Efficiency Video Coding(高效率視頻編碼),是比H.264更加優秀的一種視頻壓縮標準(也稱為 H.265)。HEVC 在低碼率 ...
  • Android精選源碼 " Android圖片/視頻選擇,編輯和壓縮解決方案源碼 " " android方便快速實現分段效果源碼 " " Android圖像視圖的動態模糊源碼 " " android漂亮流暢的等待動畫效果源碼 " " android共同頭部的 ViewPager " " androi ...
  • 到最後也只是成功改變了中間部分的顏色。 ...
  • strong和copy是常用到的修飾符,那麼什麼時候用strong,什麼時候用copy,先上一段代碼再說(以下代碼直接在ViewController中寫); 先定義兩個數組 viewDidLoad方法 列印結果 再來看下三個數組指向的記憶體地址: 可以看到arraystrong隨著arrayMut的改 ...
  • 查找今天過生日的同學 這裡表中已經存儲了生日,所以思路是取出date_birth去今天的日期相比較 ...
  • 1、表的基本概念 每一行代表一條唯一的記錄,每一列代表記錄中的一個欄位。 2、創建表 例子: 3、查看表結構 (1)DESCRIBE語句查看表定義 語法: 例子: (2)SHOW CREATE TABLE語句查看詳細表詳細定義 語法: 例子: 註意:在顯示表詳細定義信息時,可以使用“;”、“\g”和 ...
  • (開頭閑淡)項目需要必須安裝SQL的,查了很久,斷斷續續用了各種方法,今天終於用了正確的姿(xia)勢(mo)弄成了。 最開始用的方法是調用Win的API模擬滑鼠操作安裝的,嗯,雖然勉強可以,就是有些狗屎。 大概可以放到GitHub 上丟人現眼了 今天搜資料庫創建的問題看到"無人值守安裝sql",才 ...
  • Redis 持久化之RDB和AOF Redis 有兩種持久化方案,RDB (Redis DataBase)和 AOF (Append Only File)。如果你想快速瞭解和使用RDB和AOF,可以直接跳到文章底部看總結。本章節通過配置文件,觸發快照的方式,恢複數據的操作,命令操作演示,優缺點來學習 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...