Postgres的自动增量时重复键错误发生
我有一个模型和迁移定义:
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({...})
sequelizes throwns一个错误预期,即便如此,它增加了德主键自动递增值。
例如:我创建具有id
1一个新的用户,那么我尝试创建具有重复的唯一密钥(用户名或电子邮件)的新用户的5倍,则当我成功创建用户,主键id
变为6。
为什么出现这种情况?正确的将是按照顺序,如果错误则不会增加,只有当用户被成功插入递增。
回答如下:我应该由一个序列生成的值。
那么这是所有DBMS序列的正常行为。
想象一下以下情形。
User 1
要求一个新的ID。他得到id = 1
。User 2
要求一个新的ID。他得到id = 2
。User 1
未能在从属表中插入一条记录。他执行rollback
。User 2
成功插入每一个他所需要的。他执行commit
。
现在想象一下,需要何种重用id = 1
与序列,因为它没有提交。
- 滚动序列回1?复杂,因为它需要记住它返回
id = 2
给其他用户。 - 替代哪些用户2已经通过插入
id=1
?昂贵,由于外键和风险(User 2
可以使用id=2
映射到内存的对象软件,它是来不及更改DB的ID) - 使用户2等到用户1已经提交或回滚了他的事务知道该怎么回报?每个人都在等待所有的时间。
最重要的是,在id
连续值插入记录仍然不足以为它连续入住。上表中的第delete
将打破了这一切。
结论:确保IDS是连续的成本是疯狂的DB的性能和价值是不存在的,因为它可以在任何时候打破。
Postgres的自动增量时重复键错误发生
我有一个模型和迁移定义:
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({...})
sequelizes throwns一个错误预期,即便如此,它增加了德主键自动递增值。
例如:我创建具有id
1一个新的用户,那么我尝试创建具有重复的唯一密钥(用户名或电子邮件)的新用户的5倍,则当我成功创建用户,主键id
变为6。
为什么出现这种情况?正确的将是按照顺序,如果错误则不会增加,只有当用户被成功插入递增。
回答如下:我应该由一个序列生成的值。
那么这是所有DBMS序列的正常行为。
想象一下以下情形。
User 1
要求一个新的ID。他得到id = 1
。User 2
要求一个新的ID。他得到id = 2
。User 1
未能在从属表中插入一条记录。他执行rollback
。User 2
成功插入每一个他所需要的。他执行commit
。
现在想象一下,需要何种重用id = 1
与序列,因为它没有提交。
- 滚动序列回1?复杂,因为它需要记住它返回
id = 2
给其他用户。 - 替代哪些用户2已经通过插入
id=1
?昂贵,由于外键和风险(User 2
可以使用id=2
映射到内存的对象软件,它是来不及更改DB的ID) - 使用户2等到用户1已经提交或回滚了他的事务知道该怎么回报?每个人都在等待所有的时间。
最重要的是,在id
连续值插入记录仍然不足以为它连续入住。上表中的第delete
将打破了这一切。
结论:确保IDS是连续的成本是疯狂的DB的性能和价值是不存在的,因为它可以在任何时候打破。