重复键错误发生时的Postgres自动递增

时间:2019-02-05 04:52:32

标签: node.js postgresql sequelize.js

我有一个模型并定义了迁移:

guess -= (guess - low) // 2

}

module.exports = (sequelize, DataTypes) => {
const user = sequelize.define('user', {
    name: DataTypes.STRING,
    username: DataTypes.STRING,
    email: DataTypes.STRING,
    password: DataTypes.STRING,
},
    {})

user.associate = function (models) {
    // associations can be defined here
}

return user

当我尝试创建一个具有重复键值(在这种情况下为电子邮件或用户名)的新用户'use strict'; module.exports = { up: (queryInterface, Sequelize) => { return queryInterface.createTable('users', { id: { allowNull: false, autoIncrement: true, primaryKey: true, type: Sequelize.INTEGER }, name: { allowNull: false, type: Sequelize.STRING }, username: { unique: true, allowNull: false, type: Sequelize.STRING }, email: { allowNull: false, type: Sequelize.STRING }, password: { allowNull: false, type: Sequelize.STRING }, createdAt: { allowNull: false, type: Sequelize.DATE }, updatedAt: { allowNull: false, type: Sequelize.DATE } }); }, down: (queryInterface, Sequelize) => { return queryInterface.dropTable('users'); } }; 时,会顺序地引发错误,甚至会增加主键自动递增值。

示例:我创建一个具有user.create({...}) 1的新用户,然后尝试创建具有重复唯一键(用户名或电子邮件)的新用户5次,然后在成功创建一个用户时,键id变成6。

为什么会这样?正确的做法是遵循该顺序,如果错误然后没有增加,则仅在成功插入用户后才增加。

1 个答案:

答案 0 :(得分:1)

我认为值是由一个序列生成的。

这是所有DBMS中序列的正常行为。

想象一下以下情况。

  1. User 1要求一个新的ID。他得到id = 1
  2. User 2要求一个新的ID。他得到id = 2
  3. User 1无法在从属表中插入记录。他执行了rollback
  4. User 2成功插入了他需要的所有内容。他执行了commit

现在想象一下,由于序列未提交,要重用id = 1会是什么,

  • 将序列滚动回1 ?很复杂,因为需要记住它将id = 2返回给另一个用户。
  • 替换用户2插入的内容 id=1?由于外键和风险,价格昂贵(User 2可能会使用将id=2映射到内存中某些对象的软件,现在更改数据库中的ID为时已晚)
  • 让用户2等待用户1提交或回滚其交易,以了解返回什么?每个人都会一直在等待。

最重要的是,在id中插入具有连续值的记录仍不足以使其保持连续。桌子上的第一个delete会将其分解。

结论:确保id连续的成本对于数据库性能而言是疯狂的,并且该值不存在,因为它随时可能崩溃。