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,本来功能都没时间写,哪有时间来开会细细来分析代码.软件能跑就行, ...
随机推荐
- .Net 上传图片之前获取图片的宽高
Stream st = Request.Files[0].InputStream; Byte[] buffer = new Byte[st.Length]; ...
- docker下编译mangoszero WOW60级服务端(一)
这几天看到暴雪准备开放怀旧服的新闻,突然想到几年前用大芒果window一键服务端自己搭建过服务,就想着在Linux环境下重新编译一套,毕竟Linux作为服务端,性能和稳定性都会高一些,于是在mac虚拟 ...
- ASP.NET Core 应用程序Startup类介绍
Startup类配置服务和应用程序的请求管道. Startup 类 ASP.NET Core应用程序需要一个启动类,按照惯例命名为Startup.在主程序的Web Host生成器(WebHostBui ...
- C#泛型集合之List
1.命名空间:System.Collections.Generic(程序集:mscorlib)2.描述: 1).表示可通过索引访问的对象的强类型列表:提供用于对列表进行搜索.排序和操作的方法. 2). ...
- DbContext 和ObjectContext
近日学习新知识,用到CallContext数据槽,一直使用ObjectContext 但同时又在学习EF CodeFirst,上下文定义使用的 DbContext 这时问题来了,如何把DbContex ...
- [转载] Java集合框架之小结
转载自http://jiangzhengjun.iteye.com/blog/553191 1.Java容器类库的简化图,下面是集合类库更加完备的图.包括抽象类和遗留构件(不包括Queue的实现): ...
- innobackupex: fatal error: no ‘innodb_buffer_pool_filename’解决方法
http://www.ttlsa.com/mysql/innobackupex-1-5-1-fatal-error-no-innodb_buffer_pool_filename/
- SpringMVC---@RequestMapping
配置文件 承接第一,二章 index.jsp <%@ page language="java" contentType="text/html; charset=UT ...
- pattern
A compiled representation of a regular expression. A regular expression, specified as a string, must ...
- Verilog中变量位宽注意
Verilog中,变量定义方式可以为:reg[位宽-1:0] 数据名:reg[位宽:1] 数据名.其他变量也类似. 以reg变量cnt为例,当cnt位宽为4时,可定义为reg[3:0] cnt,或者定 ...