带有Sequelize的副本读取数据库的竞争条件

时间:2018-09-27 03:30:49

标签: sequelize.js psql database-replication

我们正在将Sequelize与带有读写数据库的AWS Aurora Postgresql数据库一起使用。将Sequelize配置为使用读取副本和写入数据库。

我们有一个users表和follows表。 User对象类型具有作为子查询的字段,例如,用户的字段afterCount:

...
followingCount: {
  type: new GraphQLNonNull(GraphQLInt),
  resolve(user) {
    return db.Follower.count({
      where: { followerId: user.id, status: "Approved" }
    });
  }
},

当我们向用户的follows表中添加一条记录,然后返回该用户实例时,followingCount不会更新。我有99%的信心,这是因为它正在从没有数据的副本/读取数据库中读取数据。我已通过禁用副本并看到问题消失来验证了这一点。

我不愿意在这些字段中添加useMaster选项,因为它否定了我们的并发策略。

这是我要拨打的确切代码:

const followingUser = await db.User.findOne({
  where: {
    id
  }
});

await db.Follower.create({
  followerId: getCurrentUserId(context),
  followingId: id,
  status: followingUser.privateProfile ? "Pending" : "Approved"
});

return followingUser.reload();

用户实例(followingCount)上的followingUser字段不返回最新计数,即使它存在于主数据库/写入数据库中。

有哪些选项?有什么办法可以将我的突变包装在一个块中,以便其中执行的任何事情都可以使用Master / Write数据库吗?可以将其包装在交易帮助中,如果可以的话,如何将交易传递给我的

任何帮助表示赞赏

psql 9.6.8

sequelize 4.38.0

2 个答案:

答案 0 :(得分:0)

在PostgreSQL中,复制可以通过多种方式进行:

  • 同步
  • 异步

如果您正在运行异步复制,则在主服务器(主服务器)上已提交事务后,数据可能会到达从服务器上。通常复制延迟很小。

您可以同步复制到任意数量的从站,以确保COMMIT仅在所需数量的PostgreSQL服务器确认后才有效。

只有足够数量的从站已确认写入,才可以返回同步事务。

所以我认为您正在使用异步复制,您需要转向同步复制。

https://www.cybertec-postgresql.com/en/services/postgresql-replication/synchronous-synchronous-replication/

为了设置同步复制,您需要在postgresql.conf文件中配置sync_standby_name和sync_commit参数。 sync_commit参数可以具有以下值:off,on,remote_write,remote_apply(Postgres 9.6功能)和本地。

More on how to set up sync replication

答案 1 :(得分:0)

我可以通过在要返回的数据库对象上调用reload()并将其传递给useMaster: true

来解决此问题。

followingUser.reload({ useMaster: true });

我创建了带有续集的票证,如果对任何人都有用,它将具有更多上下文:https://github.com/sequelize/sequelize/issues/9971