代码之家  ›  专栏  ›  技术社区  ›  CraZyCoDer

在PostgreSQL中锁定潜在事务

  •  1
  • CraZyCoDer  · 技术社区  · 2 年前

    想象一下下面的情况。有2个客户, A B . 这个

    1分钟后, B 客户决定使用相同的 Username Password ,(但第一个事务仍在处理中,我们无法应用唯一约束,因为还没有具有此用户名的用户。)

    UNIQUE CONSTRAINT

    问题是:如何避免这种情况?

    我听说过 LOCK 在PostgreSQL中(允许锁定 EXISTING ROW

    有没有提供某种功能来阻止潜在交易的功能?

    2 回复  |  直到 2 年前
        1
  •  1
  •   Laurenz Albe    2 年前

    BEGIN;
    SET lock_timeout = 1;
    INSERT INTO users (username, password) VALUES (...);
    RESET lock_timeout;
    /* the rest of the transaction */
    COMMIT;
    

    尝试创建同一用户的第二个事务不会被阻止,但会立即失败并可以回滚。

        2
  •  -1
  •   dave    2 年前

    问题是:如何避免这种情况?

    func createUser(user: User) error {
        this.db.exec('INSERT INTO users VALUES ($1, $2)', user.username, user.hashedPassword);
        this.db.withTransaction(func (tx Transaction) {
            tx.exec('DELETE FROM users WHERE username = $1', user.username);
            sp = tx.createSavepoint();
            tx.exec('INSERT INTO users VALUES ($1, $2)', user.username, user.hashedPassword);
            try {
                // your code that takes two minutes
                tx.commit();
            } catch (e) {
                tx.rollbackToSavepoint(sp);
                tx.commit();
            }           
        });
    }
    

    首先插入行,立即提交更改。现在,任何新用户都不能使用该用户名。

    然后,启动事务,删除用户。创建保存点。再次创建用户。现在,如果出现故障,不要回滚整个事务,而是回滚到保存点(在那里创建用户,然后删除,实际上是一个无操作)。如果有效,因为您删除了,然后又重新创建了,那么删除实际上是不可行的。