Postgres承诺多个查询 - nodejs

时间:2016-10-15 20:04:14

标签: node.js postgresql promise es6-promise

在阅读https://stackoverflow.com/a/14797359/4158593之后:关于nodejs单线程并且它接受async函数的第一个参数,处理它然后使用回调在一切准备就绪时做出响应。令我感到困惑的是,如果我有多个查询需要一次性解除,并告诉nodeJS通过将其添加到队列中来阻止其他请求。

为此,我意识到我需要将查询包装在另一个callback中。并且承诺做得很好。

    const psqlClient = psqlPool.connect(); 
    return psqlClient.query(`SELECT username FROM usernames WHERE username=$1`, ['me'])
    .then((data) => {
        if(!data.rows[0].username) {
           psqlClient.query(`INSERT INTO usernames (username) VALUES ('me')`);
        }
       else { ... } 
 });

在注册过程中使用此代码,以检查在插入之前是否未使用用户名。因此,nodejs将其他请求放入队列非常重要,并确保同时selectinsert。由于此代码可能允许同时发送具有相同用户名的用户选择已经使用的用户名,因此将插入两个用户名。

问题

  1. 上面的代码是否一次执行所有查询?

  2. 如果1是正确的,我是否要像这样更改代码

    const psqlClient = psqlPool.connect(); 
    return psqlClient.query(`SELECT username FROM usernames WHERE username=$1`, ['me'], function(err, reply) { 
    if(!reply.rows[0].username) {
    psqlClient.query(`INSERT INTO usernames (username) VALUES ('me')`);
    }
    });
    

    这会影响行为吗?

  3. 如果1错了,应该如何解决?我将需要这种模式(主要使用selectinsert/update一个接一个)来确保我的XML站点地图不包含超过50000个网址,方法是存储每个文件的计数我的db动态发生。

2 个答案:

答案 0 :(得分:2)

在您的案例中,唯一可以保证数据完整性的是单SELECT->INSERT个查询,此处已多次讨论。

一些例子:

你应该能够在这里找到更多;)

我还在SELECT ⇒ INSERT内的pg-promise示例中触及了此主题。

然而,有一种替代方法,可以使任何重复插入产生冲突,在这种情况下,您可以重新运行您的选择以获取新记录。但它并不总是一个合适的解决方案。

答案 1 :(得分:0)

这是来自node-postgres的创建者的引用:https://github.com/brianc/node-postgres/issues/83#issuecomment-212657287。基本上查询是排队的,但是在你有很多请求的生产中不要依赖它们。

但是,您可以使用BEGINCOMIT

var Client = require('pg').Client;

var client = new Client(/*your connection info goes here*/);
client.connect();

var rollback = function(client) {
  //terminating a client connection will
  //automatically rollback any uncommitted transactions
  //so while it's not technically mandatory to call
  //ROLLBACK it is cleaner and more correct
  client.query('ROLLBACK', function() {
    client.end();
  });
};

client.query('BEGIN', function(err, result) {
  if(err) return rollback(client);
  client.query('INSERT INTO account(money) VALUES(100) WHERE id = $1', [1], function(err, result) {
    if(err) return rollback(client);
    client.query('INSERT INTO account(money) VALUES(-100) WHERE id = $1', [2], function(err, result) {
      if(err) return rollback(client);
      //disconnect after successful commit
      client.query('COMMIT', client.end.bind(client));
    });
  });
});

退房:https://github.com/brianc/node-postgres/wiki/Transactions

然而,这并不会阻止该表。以下是解决方案列表:Update where race conditions Postgres (read committed)