【发布时间】:2019-06-17 15:59:49
【问题描述】:
当我尝试使用 knexjs 更新 5000 行时,我收到错误超时获取连接。池可能已满。”。
当我查看 CPU 使用率时。我发现 postgres pid 总是占用 90-98% 的 CPU 使用率,这是不正常的,我在每个 kenx 都尝试使用 destroy(),但它破坏了连接并且没有解决它
这是我正在使用的代码
const knexDb = knex({ client: 'pg', connection: {
host : '127.0.0.1',
user : process.env.DB_USER,
password : process.env.DB_PASSWORD,
database : process.env.DB_DATABASE,
port: process.env.DB_PORT
}});
arrayWith5ThousandObj.map(data => {
knexDb('users').where({
user: data.user,
})
.update({
product: data.product
})
.catch(err => console.error('update user products', err))
})
这是一个循环函数,每 1 分钟重复一次,我也尝试过 .finally -> knexDb.destroy() ,但它破坏了连接,我收到错误无法获取连接。
我想使用 knexjs 不断更新 5000 行或超过 10,000+ 行,而且我认为 PostgreSQL 可以处理这种其他方式,即每分钟执行 10000 次查询的大型网站都不会出现问题。问题不在服务器上,因为服务器有 10 个 CPU 和 16gb 的 RAM,所以资源不是问题,我停止了服务器上所有正在运行的进程,除了这个应用程序。 postgres pid 几乎完全不使用 CPU。所以问题在大量查询中发生。是否有批量更新,我可以使用 knexjs 一次更新所有 10,000 多行?
我最近尝试过这个解决方案
return knexDb.transaction(trx => {
const queries = [];
arrayWith5ThousandObj.forEach(data => {
const query = knexDb('users')
.where({
user: data.user,
})
.update({
product: data.product,
})
.transacting(trx); // This makes every update be in the same transaction
queries.push(query);
});
Promise.all(queries) // Once every query is written
.then(trx.commit) // We try to execute all of them
.catch(trx.rollback); // And rollback in case any of them goes wrong
});
但我得到这个错误:
{ error: deadlock detected
at Connection.parseE (/*********/connection.js:601:11)
at Connection.parseMessage (/*********/connection.js:398:19)
at Socket.<anonymous> (/**********/connection.js:120:22)
at Socket.emit (events.js:189:13)
at addChunk (_stream_readable.js:284:12)
at readableAddChunk (_stream_readable.js:265:11)
at Socket.Readable.push (_stream_readable.js:220:10)
at TCP.onStreamRead [as onread] (internal/stream_base_commons.js:94:17)
name: 'error',
length: 340,
severity: 'ERROR',
code: '40P01',
detail:
'Process 9811 waits for ShareLock on transaction 443279355; blocked by process 9808.\nProcess 9808 waits for ShareLock on transaction 443279612; blocked by process 9811.',
hint: 'See server log for query details.',
position: undefined,
internalPosition: undefined,
internalQuery: undefined,
where: 'while locking tuple (1799,4) in relation "users"',
schema: undefined,
table: undefined,
column: undefined,
dataType: undefined,
constraint: undefined,
file: 'deadlock.c',
line: '1140',
routine: 'DeadLockReport' }
【问题讨论】:
-
听起来好像 Node.js 或 Knex 为每一行打开一个新连接。
-
@a_horse_with_no_name 那么你建议如何解决这个问题
-
蓝鸟地图系列以限制并发承诺。您目前基本上同时启动了数千个连接。
-
@Gangstead 你能举个例子吗?使用上面的代码
-
@Gangstead 我曾经承诺在 1 秒后解决每个更新查询,但这不起作用,就像我要更新成千上万的数据一样,这将永远存在,是吗无论如何,在没有承诺的情况下进行查询。所以它会在不到一秒的时间内更新所有行
标签: node.js postgresql knex.js