PG 在高并发请求上承诺过多的客户端

Posted

技术标签:

【中文标题】PG 在高并发请求上承诺过多的客户端【英文标题】:PG Promise too many client on high concurrent request 【发布时间】:2022-01-05 11:21:02 【问题描述】:

我试图根据从其他表中选择的数据插入数百/千个数据,但我发现一个错误“客户端太多”,这里是错误

我正在使用 pgp (pg promise) 库,这是我的 sn-p

function call()
   for (let index = 0; index < 5; index++) 
        getPendingData().then((result) => 
            db.tx((t) => 
                let counter = 0;
                const queries = result.map((data) => 
                    counter++;
                    return db.none(`insert into test_data (id, isdeleted, parentid) values ('$uuidv1()', 0, '$uuidv1()x-$uuidv1()' ) `);
                );
                return t.batch(queries);
            );
        );
   



let  getPendingData = async () => 
     return db.task('getPendingData', async (t) => 
         return await t.any('select * from other_table');
     );



(call())

im setup max pg conn 为 100, 任何线索如何在不添加 max conn 的情况下解决这个问题?

【问题讨论】:

安装uuid-ossp,然后运行一个insert into test_data (id, isdeleted, parentid) select uuid_generate_v1()::text, 0, uuid_generate_v1()::text || 'x-' uuid_generate_v1()::text from other_table;查询。 @Bergi 我认为问题不是来自 uuid,而是来自客户端 conn 不,问题出在您的方法上。如果数据库可以在一个简单的单个查询中完成所有工作,请不要对数据库进行百分之一或数千次查询(即使在事务中)。 但是我需要在选定的查询上插入很多数据库,并且查询返回一千行 只需将查询拆分为块,仅并行运行块查询并按顺序处理所有块。例如,您可以使用 lodash chunk 函数拆分查询数组 【参考方案1】:

你的代码问题太多了,很遗憾……

你如何使用 Promise 和你如何使用 pg-promise 都是不正确的。

promise 的问题是你应该链接它们,这意味着使用来自 db.tx (return db.tx(...)) 的结果,你没有这样做,创建一个松散的 promise,结果,与事务相关的松散连接。另外,return await 是一种反模式。

pg-promise 使用的问题是您应该针对您正在创建的事务/任务上下文 t (as shown here) 执行查询。但是您正在针对 db 执行每个查询 - 而不是根连接,这会产生无数的连接请求。

另外,创建一个只执行一个查询的任务没有任何意义。

如果这还不够糟糕,您正在对值进行字符串连接,这在查询格式中是一个严格的禁忌。

最后,多个插入应该作为多行查询执行,而不是作为单独的查询执行,这会浪费性能 - 请参阅multi-row inserts。

【讨论】:

感谢pg-promise :) @madflow 不客气! :) 感谢您的建议

以上是关于PG 在高并发请求上承诺过多的客户端的主要内容,如果未能解决你的问题,请参考以下文章

Mysql在高并发情况下,防止库存超卖而小于0的解决方案

分布式缓存主要用在高并发环境下的作用?

缓存在高并发场景下的常见问题

缓存在高并发场景下的常见问题

HttpClient在高并发场景下的优化实战

互联网应用在高并发