greenplum在执行vacuum和insert产生死锁问题定位及解决方案
首先声明:未经本人同意,请勿转载,谢谢!
本人使用自己编译的开源版本的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,,),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确定),红色的线表示等待关系。


至此,产生这个问题的原因基本明晰了,那么遇到了这种情况该如何解决?
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会返回类似如下的结果(部分):

(图十)

greenplum在执行vacuum和insert产生死锁问题定位及解决方案的更多相关文章
- Greenplum 调优--VACUUM系统表
Greenplum 调优--VACUUM系统表 1.VACUUM系统表原因 Greenplum是基于MVCC版本控制的,所有的delete并没有删除数据,而是将这一行数据标记为删除, 而且update ...
- sql server中同时执行select和update语句死锁问题
原始出处 http://oecpby.blog.51cto.com/2203338/457054 最近在项目中使用SqlServer的时候发现在高并发情况下,频繁更新和频繁查询引发死锁.通常我们知道如 ...
- 监控SQL Server正在执行的SQL语句和死锁情况
原文:监控SQL Server正在执行的SQL语句和死锁情况 SELECT [Individual Query] = SUBSTRING(qt.TEXT, er.statement_start_off ...
- Mysql update后insert造成死锁原因分析及解决
系统中出现死锁的日志如下: ) TRANSACTION: , ACTIVE sec inserting mysql tables , locked LOCK WAIT lock struct(s), ...
- Python 3.6.0的sqlite3模块无法执行VACUUM语句
Python 3.6.0的sqlite3模块存在一个bug(见issue 29003),无法执行VACUUM语句. 一执行就出现异常: Traceback (most recent call last ...
- ORACLE-Kill 杀死正在执行的Oracle存储过程和死锁语句
ORACLE-Kill 杀死正在执行的Oracle存储过程和死锁语句 存储过程 1.找到正在执行的存储过程的 sid ,serial# select b.sid,b.SERIAL#,a.OBJEC ...
- postgrel执行VACUUM报VACUUM cannot run inside a transaction block
在python脚本里执行: sql_gp1 = "VACUUM dwd_access_record_inout_temp" sql_gp2 = "delete from ...
- [20180801]insert导致死锁.txt
[20180801]insert导致死锁.txt --//链接http://www.itpub.net/thread-2104135-2-1.html的讨论,自己有点疏忽了,插入主键相同也会导致死锁. ...
- sqlserver 抓取所有执行语句 SQL语句分析 死锁 抓取
原文:sqlserver 抓取所有执行语句 SQL语句分析 死锁 抓取 在多人开发中最头疼的是人少事多没有时间进行codereview,本来功能都没时间写,哪有时间来开会细细来分析代码.软件能跑就行, ...
随机推荐
- 从Matlab文件中读取mxArray类型变量-部分代码分析
这是我做的笔记,看到这个代码时觉得处理有点妙,做笔记记录之. 部分源代码: .... int main(int argc,char** argv) { char name[_FILE_NAME_LEN ...
- [DeeplearningAI笔记]ML strategy_2_3迁移学习/多任务学习
机器学习策略-多任务学习 Learninig from multiple tasks 觉得有用的话,欢迎一起讨论相互学习~Follow Me 2.7 迁移学习 Transfer Learninig 神 ...
- AngularJS学习篇(二十四)
AngularJS 应用 <html ng-app="myNoteApp"> <head> <meta charset="utf-8&quo ...
- Promise同时进入catch和then——踩坑
记录今天使用Promise遇到的一个坑--在resolve()返回运行then之后,函数又进入到了catch,源代码大意如下: var pro = function() { return new Pr ...
- MySQL性能建议者mysqltuner.pl和pt-variable-advisor
[root@etch171 ~]# mysqltuner.pl --host >> MySQLTuner - Major Hayden <major@mhtx.net> > ...
- curl安装
问题1: curl: error while loading shared libraries: libcurl.so.4: cannot open shared object file: No su ...
- java SE 基础概念梳理(一)
(一)First 摘要:Java概述.Java开发环境搭建.程序开发流程 Java概述 Java的应用 开发QQ.迅雷程序(桌面应用软件)开发淘宝.京东(互联网应用软件) Java的擅长 互联网: ...
- html5+ XMLHttpRequest
XMLHttpRequest 让发送一个HTTP请求变得非常容易.你只需要简单的创建一个请求对象实例,打开一个URL,然后发送这个请求.当传输完毕后,结果的HTTP状态以及返回的响应内容也可以从请求对 ...
- 第二个MapReduce
大家在学习Hadoop的MapReduce的时候,90%的第一个程序都是WordCount,所以在这里分享一下我的第二个MapReduce程序.对于学习编程语言的人来说,有时候代码是最好的沟通方式之一 ...
- spring boot 中 Mybatis plus 多数据源的配置方法
最近在学习spring boot,发现在jar包依赖方面做很少的工作量就可以了,对于数据库操作,我用的比较多的是mybatis plus,在中央仓库已经有mybatis-plus的插件了,对于单数据源 ...