PostgreSQL 如何检测分布式死锁 - postgrespro pg_shardman

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

标签

PostgreSQL , postgrespro , pg_shardman , 分布式死锁


背景

单机的死锁检测是比较容易实现的,通过判断等待中的事务是否查询环状,即可实现。例如下面的图,A等B, B等C, C等A,出现环状,即认为死锁。

pic

而对于分布式事务,由于相互等待的事务可能出现在不同的数据节点上,如何判断分布式死锁呢?

为了判断是否有环,必须引入全局事务号,或者有标识可以在每个数据节点上标识出来对应的事务。这样才能画出等待图形,判断是否出现环状。

另一方面由于判断分布式事务是否出现死锁,在每个数据节点上读取锁等待信息,所以不同的数据节点读取等待信息是有时间差的,因此仅凭一次的环无法判断是否真的死锁(例如你在查询到等待后,查看其它节点时,实际上之前的等待已经消失的情况,是“假死锁”),需要两次查询,并且等待环(包括GID在内等信息完全一致的环)出现在两次查询中时,这个环才认为是真正的死锁。

pic

postgrespro pg_shardman

pg_shardman 没有内置死锁检测的功能,而是通过开放一个UDF接口,用户调用这个接口,无限循环,检测是否有分布式死锁,随机cancel造成分布式死锁的其中一个query。

monitor(check_timeout_sec int = 5, rm_node_timeout_sec int = 60)  

Monitor cluster for presence of distributed deadlocks and node failures. This function is intended to be executed at shardlord and is redirected to shardlord been launched at any other node. It starts infinite loop which polls all clusters nodes, collecting local lock graphs from all nodes. Period of poll is specified by check_timeout_sec parameter (default value is 5 seconds). Local lock graphs are combined into global lock graph which is analyzed for the presence of loops. A loop in the lock graph means distributed deadlock. Monitor function tries to resolve deadlock by canceling one or more backends involved in the deadlock loop (using pg_cancel_backend function, which doesn't actually terminate backend but tries to cancel current query). Canceled backend is randomly chosen within deadlock loop. Since not all deadlock members are hanged in 'active query' state, it might be needed to send cancel several times.

Since local graphs collected from all nodes do not form consistent global snapshot, false postives are possible: edges in deadlock loop correspond to different moment of times. To prevent false deadlock detection, monitor function doesn't react on detected deadlock immediately. Instead of it, previous deadlock loop located at previous iteration is compared with current deadlock loop and only if they are equal, deadlock is reported and resolving is performed.

If some node is unreachable then monitor function prints correspondent error message and retries access until rm_node_timeout_sec timeout expiration. After it node is removed from the cluster using shardman.rm_node function. If redundancy level is non-zero, then primary partitions from the disabled node are replaced with replicas. Finally pg_shardmanperforms recovery of distributed transactions for which failed node was the coordinator. It is done using shardman.recover_xacts() function which collects status of distributed transaction at all participants and tries to make decision whether it should be committed or aborted. If rm_node_timeout_sec is NULLmonitor will not remove nodes.

参考

https://github.com/postgrespro/pg_shardman/blob/native_partitioning/pg_shardman--0.0.3.sql

pg_shardman提供的分布式死锁检测依赖的一些对象。

-- Type to represent vertex in lock graph  
create type process as (node int, pid int);  
  
-- View to build lock graph which can be used to detect global deadlock.  
-- Application_name is assumed pgfdw:$system_id:$coord_pid  
-- gid is assumed pgfdw:$timestamp:$sys_id:$pid:$xid:$participants_count:$coord_count  
-- Currently we are oblivious about lock modes and report any wait -> hold edge  
-- on the same object and therefore might produce false loops. Furthermore,  
-- we have not idea about locking queues here. Probably it is better to use  
-- pg_blocking_pids, but it seems to ignore prepared xacts.  
CREATE VIEW lock_graph(wait, hold) AS  
	-- local dependencies  
    -- If xact is already prepared, we take node and pid of the coordinator.  
	SELECT  
		ROW(shardman.get_my_id(),  
			wait.pid)::shardman.process,  
	 	CASE WHEN hold.pid IS NOT NULL THEN  
		    ROW(shardman.get_my_id(), hold.pid)::shardman.process  
		ELSE -- prepared  
			ROW(shardman.get_node_by_sysid(split_part(gid, ':', 3)::bigint),  
				split_part(gid, ':', 4)::int)::shardman.process  
		END  
     FROM pg_locks wait, pg_locks hold LEFT OUTER JOIN pg_prepared_xacts twopc  
			  ON twopc.transaction=hold.transactionid  
	WHERE  
		NOT wait.granted AND wait.pid IS NOT NULL AND hold.granted AND  
		-- waiter waits for the the object holder locks  
		wait.database IS NOT DISTINCT FROM hold.database AND  
		wait.relation IS NOT DISTINCT FROM hold.relation AND  
		wait.page IS NOT DISTINCT FROM hold.page AND  
		wait.tuple IS NOT DISTINCT FROM hold.tuple AND  
		wait.virtualxid IS NOT DISTINCT FROM hold.virtualxid AND  
		wait.transactionid IS NOT DISTINCT FROM hold.transactionid AND -- waiting on xid  
		wait.classid IS NOT DISTINCT FROM hold.classid AND  
		wait.objid IS NOT DISTINCT FROM hold.objid AND  
		wait.objsubid IS NOT DISTINCT FROM hold.objsubid AND  
		 -- this is most probably truism, but who knows  
		(hold.pid IS NOT NULL OR twopc.gid IS NOT NULL)  
	UNION ALL  
	-- if this fdw backend is busy, potentially waiting, add edge coordinator -> fdw  
	SELECT ROW(shardman.get_node_by_sysid(split_part(application_name, ':', 2)::bigint),  
			   split_part(application_name,':',3)::int)::shardman.process,  
		   ROW(shardman.get_my_id(),  
			   pid)::shardman.process  
	FROM pg_stat_activity WHERE application_name LIKE 'pgfdw:%' AND wait_event<>'ClientRead'  
	UNION ALL  
	-- otherwise, coordinator itself is busy, potentially waiting, so add fdw ->  
	-- coordinator edge  
	SELECT ROW(shardman.get_my_id(),  
			   pid)::shardman.process,  
		   ROW(shardman.get_node_by_sysid(split_part(application_name,':',2)::bigint),  
			   split_part(application_name,':',3)::int)::shardman.process  
	FROM pg_stat_activity WHERE application_name LIKE 'pgfdw:%' AND wait_event='ClientRead';  
  
-- Pack lock graph into comma-separated string of edges like "2:17439->4:30046",  
-- i.e. pid 17439 on node 2 waits for pid 30046 on node 4  
CREATE FUNCTION serialize_lock_graph() RETURNS TEXT AS $$  
	SELECT COALESCE(  
		string_agg((wait).node || ':' || (wait).pid || '->' ||  
				   (hold).node || ':' || (hold).pid,  
				   ','),  
		'')  
	FROM shardman.lock_graph;  
$$ LANGUAGE sql;  
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
2月前
|
关系型数据库 分布式数据库 PolarDB
电子书阅读分享《PolarDB开发者大会:分布式的PolarDB》
电子书阅读分享《PolarDB开发者大会:分布式的PolarDB》
32 6
|
2月前
|
存储 关系型数据库 分布式数据库
选300平米别墅还是90平米小平层?一文带你读懂PolarDB分布式版集分一体化
1月17日,在阿里云PolarDB开发者大会上,阿里云PolarDB分布式产品部负责人黄贵发表了《分布式的PolarDB:分布式的能力,一体化的体验》主题演讲。
|
3月前
|
存储 关系型数据库 分布式数据库
选300平米别墅还是90平米小平层?一文带你读懂PolarDB分布式版集分一体化
PolarDB分布式版内核上具备了集中式分布式一体化的技术融合,支持集中式和分布式两种形态无缝切换。
选300平米别墅还是90平米小平层?一文带你读懂PolarDB分布式版集分一体化
|
6月前
|
SQL 存储 Web App开发
PolarDB-X 分布式数据库中的外键
外键是关系型数据库中非常便利的一种功能,它通过一个或多个列为两张表建立连接,从而允许跨表交叉引用相关数据。外键通过约束来保持数据的一致性,通过级联来同步数据在多表间的更新和删除。在关系数据库系统中,大多数表都遵循外键的概念。
|
7天前
|
Docker 容器 关系型数据库
【PolarDB-X从入门到精通】 第四讲:PolarDB分布式版安装部署(源码编译部署)
本期课程将于4月11日19:00开始直播,内容包括源码编译基础知识和实践操作,课程目标是使学员掌握源码编译部署技能,为未来发展奠定基础,期待大家在课程中取得丰富的学习成果!
【PolarDB-X从入门到精通】 第四讲:PolarDB分布式版安装部署(源码编译部署)
|
存储 关系型数据库 MySQL
分布式事物【悲观锁、乐观锁、读锁、写锁、间隙锁、临键锁 、 表锁、行锁、页面锁、 如何避免死锁】(二)-全面详解(学习总结---从入门到深化)
分布式事物【悲观锁、乐观锁、读锁、写锁、间隙锁、临键锁 、 表锁、行锁、页面锁、 如何避免死锁】(二)-全面详解(学习总结---从入门到深化)
47 0
|
4月前
|
关系型数据库 分布式数据库 数据库
开营啦|PolarDB分布式版训练营,参营享限定版新年好礼
有机会领取阿里云新年礼盒大礼包等价值千元好礼
开营啦|PolarDB分布式版训练营,参营享限定版新年好礼
|
4月前
|
存储 关系型数据库 MySQL
[重磅更新]PolarDB-X V2.3 集中式和分布式一体化开源发布
2023年云栖大会,PolarDB-X 正式发布 2.3.0版本,重点推出PolarDB-X标准版(集中式形态),将PolarDB-X分布式中的DN节点提供单独服务,支持paxos协议的多副本模式、lizard分布式事务引擎,可以100%兼容MySQL。同时在性能场景上,采用生产级部署和参数(开启双1 + Paxos多副本强同步),相比于开源MySQL 8.0.34,PolarDB-X在读写混合场景上有30~40%的性能提升,可以作为开源MySQL的最佳替代选择。
|
2月前
|
关系型数据库 分布式数据库 PolarDB
电子书阅读分享《PolarDB开发者大会:分布式的PolarDB》
电子书阅读分享《PolarDB开发者大会:分布式的PolarDB》
24 4
|
2月前
|
SQL 关系型数据库 分布式数据库
PolarDB分布式版2023年度干货合集
PolarDB 分布式版 (PolarDB for Xscale,简称“PolarDB-X”) 是阿里云自主设计研发的高性能云原生分布式数据库产品,为用户提供高吞吐、大存储、低延时、易扩展和超高可用的云时代数据库服务。本文整理了PolarDB-X干货合集内容,希望对你学习和深入了解PolarDB-X有很大帮助。

相关产品

  • 云原生数据库 PolarDB