node.js - 发生重复键错误时 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({...})
具有重复键值(在这种情况下为电子邮件或用户名)的新用户时,续集会按预期抛出错误,即使这样它也会增加主键自动增量值。
示例:我创建了一个具有id
1 的新用户,然后我尝试创建 5 次具有重复唯一键(用户名或电子邮件)的新用户,然后当我成功创建用户时,主键id
变为 6。
为什么会发生这种情况?正确的做法是按照顺序,如果错误则不增加,仅在用户成功插入时增加。
解决方案
我认为值是由序列生成的。
那么这是所有 DBMS 中序列的正常行为。
想象以下场景。
User 1
要求一个新的身份证。他得到id = 1
.User 2
要求一个新的身份证。他得到id = 2
.User 1
无法在依赖表中插入记录。他执行一个rollback
.User 2
成功插入他需要的每一个。他执行一个commit
.
现在想象一下重用序列需要什么id = 1
,因为它没有提交。
- 将序列回滚到 1?复杂,因为它需要记住它返回
id = 2
给另一个用户。 - 替换用户 2 插入的内容
id=1
?由于外键而昂贵且有风险(User 2
可能使用映射id=2
到内存中某个对象的软件,更改数据库中的 id 为时已晚) - 让用户 2 等到用户 1 提交或回滚他的事务后才知道要返回什么?每个人都会一直在等待。
最重要的是,插入具有连续值的记录id
仍然不足以使其保持连续。桌子上的第一个delete
将打破一切。
结论:确保 id 连续的成本对于数据库性能来说是疯狂的,并且该值不存在,因为它可能随时崩溃。
推荐阅读
- matlab - 将python字典传递给matlab
- php - 用逗号和字符串分隔数组 PHP
- excel - Excel在数组中返回多个部分字符串匹配
- css - 使用 :focus-within 时单击 :hover 元素中的链接会卡住
- javascript - Firebase 从已删除数据中删除孤立数据
- php - 在页面加载时执行 php 短代码
- php - php - 不能将 PDOStatement 类型的对象用作带有 Google Cloud Messaging 的数组
- c# - FileSystemWatcher 和计时器一起使用
- python - pip install mysqlclient 在 Ubuntu 上使用 docker 上的 python 2.7 失败
- java - 何时使用 concurrenthashmap 与 hashmap 进行 put 和 get