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 在 Postgres 中更新插入

Node.js Sequelize UUID 主键 + Postgres

postgres 与 node.js 连接中的 SASL 错误

使用 Node.js 从 Redshift 将数据复制到 postgres

使用临时表调用 postgres 函数的节点导致“内存泄漏”