Postgres 承诺多个查询 - nodejs
Postgres promise multiple queries - nodejs
阅读后:关于nodejs单线程,它接受异步函数的第一个参数,处理它,然后在一切准备就绪时使用回调进行响应。让我感到困惑的是,如果我有多个查询需要一次全部排除并告诉 nodeJS 通过将它们添加到队列中来阻止其他请求怎么办。
为此,我意识到我需要将我的查询包装在另一个 callback
中。并且 promises 做得很好。
const psqlClient = psqlPool.connect();
return psqlClient.query(`SELECT username FROM usernames WHERE username=`, ['me'])
.then((data) => {
if(!data.rows[0].username) {
psqlClient.query(`INSERT INTO usernames (username) VALUES ('me')`);
}
else { ... }
});
此代码在注册期间使用,用于在插入前检查用户名是否未被占用。所以nodejs将其他请求放入队列中非常重要,并确保同时select
和insert
。因为此代码可能允许具有相同用户名的人同时发送给 select 已被占用的用户名,因此将插入两个用户名。
问题
上面的代码是一次性执行查询吗?
如果 1
是正确的,如果我要像这样更改代码
const psqlClient = psqlPool.connect();
return psqlClient.query(`SELECT username FROM usernames WHERE username=`, ['me'], function(err, reply) {
if(!reply.rows[0].username) {
psqlClient.query(`INSERT INTO usernames (username) VALUES ('me')`);
}
});
这会影响行为吗?
如果1
是错误的,应该如何解决?我将需要这种模式(主要是依次使用 select
和 insert/update
),例如通过存储计数来确保我的 XML 站点地图包含的网址不超过 50000 个对于我的数据库中动态发生的每个文件。
在您的案例中,唯一可以保证数据完整性的是单个 SELECT->INSERT
查询,这已在此处讨论过多次。
一些例子:
- Is SELECT or INSERT in a function prone to race conditions?
您应该可以在这里找到更多信息;)
我也在 SELECT ⇒ INSERT example within pg-promise 中提到了这个主题。
但是有一个替代方案,可以使任何重复的插入产生冲突,在这种情况下,您可以重新运行您的select来获取新记录。但这并不总是合适的解决方案。
这是来自 node-postgres 的创建者的参考:https://github.com/brianc/node-postgres/issues/83#issuecomment-212657287。基本上查询是排队的,但在有很多请求的生产中不要依赖它们....
但是您可以使用 BEGIN
和 COMIT
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], function(err, result) {
if(err) return rollback(client);
client.query('INSERT INTO account(money) VALUES(-100) WHERE id = ', [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
但是这不会阻止 table。以下是解决方案列表:Update where race conditions Postgres (read committed)
阅读后:关于nodejs单线程,它接受异步函数的第一个参数,处理它,然后在一切准备就绪时使用回调进行响应。让我感到困惑的是,如果我有多个查询需要一次全部排除并告诉 nodeJS 通过将它们添加到队列中来阻止其他请求怎么办。
为此,我意识到我需要将我的查询包装在另一个 callback
中。并且 promises 做得很好。
const psqlClient = psqlPool.connect();
return psqlClient.query(`SELECT username FROM usernames WHERE username=`, ['me'])
.then((data) => {
if(!data.rows[0].username) {
psqlClient.query(`INSERT INTO usernames (username) VALUES ('me')`);
}
else { ... }
});
此代码在注册期间使用,用于在插入前检查用户名是否未被占用。所以nodejs将其他请求放入队列中非常重要,并确保同时select
和insert
。因为此代码可能允许具有相同用户名的人同时发送给 select 已被占用的用户名,因此将插入两个用户名。
问题
上面的代码是一次性执行查询吗?
如果
1
是正确的,如果我要像这样更改代码const psqlClient = psqlPool.connect(); return psqlClient.query(`SELECT username FROM usernames WHERE username=`, ['me'], function(err, reply) { if(!reply.rows[0].username) { psqlClient.query(`INSERT INTO usernames (username) VALUES ('me')`); } });
这会影响行为吗?
如果
1
是错误的,应该如何解决?我将需要这种模式(主要是依次使用select
和insert/update
),例如通过存储计数来确保我的 XML 站点地图包含的网址不超过 50000 个对于我的数据库中动态发生的每个文件。
在您的案例中,唯一可以保证数据完整性的是单个 SELECT->INSERT
查询,这已在此处讨论过多次。
一些例子:
- Is SELECT or INSERT in a function prone to race conditions?
您应该可以在这里找到更多信息;)
我也在 SELECT ⇒ INSERT example within pg-promise 中提到了这个主题。
但是有一个替代方案,可以使任何重复的插入产生冲突,在这种情况下,您可以重新运行您的select来获取新记录。但这并不总是合适的解决方案。
这是来自 node-postgres 的创建者的参考:https://github.com/brianc/node-postgres/issues/83#issuecomment-212657287。基本上查询是排队的,但在有很多请求的生产中不要依赖它们....
但是您可以使用 BEGIN
和 COMIT
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], function(err, result) {
if(err) return rollback(client);
client.query('INSERT INTO account(money) VALUES(-100) WHERE id = ', [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
但是这不会阻止 table。以下是解决方案列表:Update where race conditions Postgres (read committed)