Greenplum max_prepared_transactions 设置不正确时的症状 - too many clients already

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS AI 助手,专业版
简介:

背景

Greenplum分布式事务使用2PC提交,因此需要依赖max_prepared_transactions参数的配置。

原文

https://www.cnblogs.com/chenminklutz/p/8946269.html

max_prepared_transactions 应该至少设置为 max_connections 一样大。

正文

max_prepared_transactions是greenplum的一个参数,以下是官方文档

Sets the maximum number of transactions that can be in the prepared state simultaneously. Greenplum uses prepared transactions internally to ensure data integrity across the segments. This value must be at least as large as the value of max_connections on the master. Segment instances should be set to the same value as the master.

Value Range Default Set Classifications
integer 250 on master 
250 on segments
local 
system 
restart

参数类型:本地,系统级,需要重启生效。

当这个参数设置的足够小时,如果max_prepared_transactions使用耗尽,会报错如下:

FATAL: sorry, too many clients already.  
DETAIL: There are no more available slots in the sharedSnapshotArray.  
HINT: Another piece of code should have detected that we have too many clients.this probably means that someone isn't releasing their slot properly.  

然后其他人就连不上数据库。

开始解决问题:

查看数据库状态,gpstate -s

正常,segment没有挂

但是发现master current role变成了utility,正常应该是是dispatch啊。

肯定有问题,继续找。

手动pg_terminate_backend()最早的30个进程,正常啦,master current role也回去了,其他人也能连上了。

过一会儿又不行啦。

上源码搜sharedSnapshotArray,发现如下判断就会报这个错

    if (arrayP->numSlots >= arrayP->maxSlots || arrayP->nextSlot == -1)  
    {  
        /*  
         * Ooops, no room.  this shouldn't happen as something else should have  
         * complained if we go over MaxBackends.  
         */  
        LWLockRelease(SharedSnapshotLock);  
        ereport(FATAL,  
                (errcode(ERRCODE_TOO_MANY_CONNECTIONS),  
                 errmsg("sorry, too many clients already."),  
                 errdetail("There are no more available slots in the sharedSnapshotArray."),  
                 errhint("Another piece of code should have detected that we have too many clients."  
                         " this probably means that someone isn't releasing their slot properly.")));  
    }  

继续顺藤摸瓜搜maxSlots,看是怎么确定的值。

        /*  
         * We're the first - initialize.  
         */  
        sharedSnapshotArray->numSlots = 0;  
  
        /* TODO:  MaxBackends is only somewhat right.  What we really want here  
         *        is the MaxBackends value from the QD.  But this is at least  
         *          safe since we know we dont need *MORE* than MaxBackends.  But  
         *        in general MaxBackends on a QE is going to be bigger than on a  
         *          QE by a good bit.  or at least it should be.  
         *  
         * But really, max_prepared_transactions *is* what we want (it  
         * corresponds to the number of connections allowed on the  
         * master).  
         *  
         * slotCount is initialized in SharedSnapshotShmemSize().  
         */  
        sharedSnapshotArray->maxSlots = slotCount;  
        sharedSnapshotArray->nextSlot = 0;  
  
        sharedSnapshotArray->slots = (SharedSnapshotSlot *)&sharedSnapshotArray->xips;  
  
        /* xips start just after the last slot structure */  
        xip_base = (TransactionId *)&sharedSnapshotArray->slots[sharedSnapshotArray->maxSlots];  

继续slotCount,上边有注释说slotCount在SharedSnapshotShmemSize里被初始化

/*  
 * Report shared-memory space needed by CreateSharedSnapshot.  
 */  
Size  
SharedSnapshotShmemSize(void)  
{  
    Size        size;  
  
    xipEntryCount = MaxBackends + max_prepared_xacts;  
  
    slotSize = sizeof(SharedSnapshotSlot);  
    slotSize += mul_size(sizeof(TransactionId), (xipEntryCount));  
    slotSize = MAXALIGN(slotSize);  
  
    /*  
     * We only really need max_prepared_xacts; but for safety we  
     * multiply that by two (to account for slow de-allocation on  
     * cleanup, for instance).  
     */  
    slotCount = NUM_SHARED_SNAPSHOT_SLOTS;  
  
    size = offsetof(SharedSnapshotStruct, xips);  
    size = add_size(size, mul_size(slotSize, slotCount));  
  
    return MAXALIGN(size);  
}  

全局变量NUM_SHARED_SNAPSHOT_SLOTS

#define NUM_SHARED_SNAPSHOT_SLOTS (2 * max_prepared_xacts)  

二倍的max_prepared_transactions参数值。其实上边的英文注释也说啦:我们实际上只需要max_prepared_transactions,但是为了安全我们把他乘二,比如清除时的缓慢反分配。

所以查看系统的max_prepared_transactions的值,发现只有50,此处笑cry,捂脸哭。

修改max_prepared_transactions等于master的max_connections,gpconfig -c max_prepared_transactions -v 1500,重启数据库gpstop -a -M fast

查看max_prepared_transactions,已经生效。

OK问题解决!!

问题模拟

gpconfig -c max_prepared_transactions -v 1
gpstop -M fast -a
gpstart -a

postgres=# show max_prepared_transactions ;
 max_prepared_transactions 
---------------------------
 1
(1 row)


postgres=# create table test(id int, info text);
NOTICE:  Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'id' as the Greenplum Database data distribution key for this table.
HINT:  The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
CREATE TABLE
postgres=# begin;
BEGIN
postgres=# insert into test select generate_series(1,1000),'test';
INSERT 0 1000


-- 会话2
postgres=# \set VERBOSITY verbose
postgres=# insert into test select generate_series(1,1000),'test';
FATAL:  XX000: the limit of 1 distributed transactions has been reached. (cdbtm.c:2569)
DETAIL:  The global user configuration (GUC) server parameter max_prepared_transactions controls this limit.
LOCATION:  createDtx, cdbtm.c:2569
server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.
目录
相关文章
|
8月前
|
NoSQL Redis
跨redis迁移数据的增量迁移方案和工具
面对这个不能完全覆盖的需求,使用RDB备份的需求是无法满足,因为RDB文件会将B的全部数据改为A的数据,显然是不可行的。后来我用了yunedit-redis,这款客户端工具,完美实现了数据的迁移,而且全程都在客户端操作,无需通过编码的方式来实现。
361 1
|
监控 数据可视化 数据挖掘
项目管理精细化:如何提高执行效率?
在竞争激烈的商业环境中,高效的项目管理至关重要。本文探讨了如何优化项目管理流程,包括明确目标、制定可执行计划、建立沟通机制、应对风险及利用可视化工具(如看板)提升效率。通过持续复盘与优化,团队能不断提升执行力,确保项目按时按质交付。
494 19
|
算法 关系型数据库 数据库
德哥的PostgreSQL私房菜 - 史上最屌PG资料合集
看完并理解这些文章,相信你会和我一样爱上PostgreSQL,并成为PostgreSQL的布道者。 沉稳的外表无法掩饰PG炙热的内心 。 扩展阅读,用心感受PostgreSQL 内核扩展 《找对业务G点, 体验酸爽 - PostgreSQL内核扩展指南》https://yq.
59328 152
|
存储 JSON API
如何创建自己的数据集!!!
本文介绍了如何创建和使用自定义数据集,特别是针对GitHub Issues的语料库。内容涵盖了从获取数据、清理数据到扩充数据集的全过程,最终将数据集上传到Hugging Face Hub并与社区分享。具体步骤包括使用GitHub REST API下载Issues,通过Python脚本进行数据处理,以及添加评论信息。此外,还介绍了如何创建数据集卡片,以提供详细的背景信息和使用指南。
451 0
|
存储 安全 Java
Spring Boot中的配置文件加密
Spring Boot中的配置文件加密
|
Docker 容器
docker overlay2占用大量磁盘空间处理方法
docker overlay2占用大量磁盘空间处理方法
2472 0
|
SQL 关系型数据库 中间件
postgresql从入门到精通 - 第35讲:中间件PgBouncer部署
postgresql技术大讲堂,从入门到精通 - 第35讲:中间件PgBouncer部署
640 1
|
Java API 数据库
SpringBoot - 优雅的处理【长事务】
SpringBoot - 优雅的处理【长事务】
521 0
|
存储 运维 Java
一文带你了解云HIS
一文带你了解云HIS
857 1