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
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...