node.js + postgres 数据库事务管理
Posted
技术标签:
【中文标题】node.js + postgres 数据库事务管理【英文标题】:node.js + postgres database transaction management 【发布时间】:2012-03-08 07:32:46 【问题描述】:我们有一个现有的 SQL 数据库,我正在编写一个使用直接 SQL 访问它的 node.js 服务器,使用这个 postgres 驱动程序模块:
https://github.com/brianc/node-postgres
到目前为止,我找不到与 postgres 一起使用的事务管理节点模块。有人知道吗?最好有一些实际用途?
其次,在更高的层面上,我们正在评估 node.js 是否可以真正取代 Java,作为服务器潜在处理量的实际解决方案。事务管理是我们必须解决的问题之一。因此,对此进行一些深入了解也会很有用。
目前,我只是在节点服务器请求开始时发出 sql BEGIN 并在结束时发出 ROLLBACK 或 COMMIT。但是,我(也许很明显)不熟悉围绕 SQL 事务管理的现实问题。如果有人能简要解释一下事务管理框架解决的问题,我会觉得它很有用。
编辑:我正在使用 postgres 驱动程序的内置连接池机制,并且 http 请求中的所有查询都是在从池中获得的同一连接上发出的。首先发出 BEGIN,然后无论具体的 http 请求做什么,然后是 COMMIT 或 ROLLBACK。
谢谢。
【问题讨论】:
【参考方案1】:事务管理是一个相当大的主题。对于我想象的你正在做的事情,你会想要使用 AUTOCOMMIT 模式。这基本上意味着您将依赖 PostgreSQL 来开始/提交您的所有语句(或者换句话说,您的所有语句将在它们自己的事务中运行,彼此没有关系)。确定 AUTOCOMMIT 模式是否适合您的一种简单方法是确定您不需要使用 ROLLBACK。 AUTOCOMMIT 模式的一个巨大好处是,即使是最愚蠢的连接池工具也无法搞砸。
有关事务管理的详细信息,请先查看http://www.postgresql.org/docs/9.1/static/transaction-iso.html,无论您做什么,请确保您不使用或编写一个让您处于“IDLE in transaction”领域的幼稚框架。最后,既然你提到了“高容量”,我应该问一下你的读写平衡是多少。如果它强烈支持读取行为,那么您应该考虑编写代码以使用 memcached。最简单(但远非最有效)的方法是使用PQC。
【讨论】:
感谢您提供的所有信息。我们确实需要 ROLLBACK,因为我们的请求发出了许多需要成为原子单元的更新语句。我会看看那个文件和 PQC。【参考方案2】:pg-promise 库很好地处理了事务管理:
db.tx(t =>
return t.batch([
t.query('UPDATE users SET active = $1 WHERE id = $2', [true, 123]),
t.query('INSERT INTO audit(event, id) VALUES($1, $2)', ['activate', 123])
]);
)
.then(data =>
// success;
)
.catch(error =>
// error;
);
【讨论】:
你知道如何使用这种方法设置事务级别吗? @Derek See Configurable Transactions【参考方案3】:寻找续集 http://docs.sequelizejs.com/en/latest/api/transaction/
启动事务时可能使用的隔离级别:
READ_UNCOMMITTED: "READ UNCOMMITTED",
READ_COMMITTED: "READ COMMITTED",
REPEATABLE_READ: "REPEATABLE READ",
SERIALIZABLE: "SERIALIZABLE"
传入所需的级别作为第一个参数:
return sequelize.transaction(
isolationLevel: Sequelize.Transaction.SERIALIZABLE
, function (t)
// your transactions
).then(function(result)
// transaction has been committed. Do something after the commit if required.
).catch(function(err)
// do something with the err.
);
【讨论】:
【参考方案4】:你只需要一个包装函数。
我更喜欢使用纯 pg
库,因为它已经包含了交易的一切。
这是我的 TypeScript 示例:
import PoolClient from "pg"
import pool from "../database"
const tx = async (callback: (client: PoolClient) => void) =>
const client = await pool.connect();
try
await client.query('BEGIN')
try
await callback(client)
await client.query('COMMIT')
catch (e)
await client.query('ROLLBACK')
finally
client.release()
export tx
用法:
let result;
await tx(async client =>
const rows = await client.query< cnt: string >('SELECT COUNT(*) AS cnt FROM users WHERE username = $1', [username]);
result = parseInt(rows[0].cnt) > 0;
);
【讨论】:
以上是关于node.js + postgres 数据库事务管理的主要内容,如果未能解决你的问题,请参考以下文章
AWS:启动启动服务器(Node.js + Postgres)
Node.js Sequelize UUID 主键 + Postgres
postgres 与 node.js 连接中的 SASL 错误