postgresql - 带有 SEQUENCE 的 PostgreSQL“重复键违规”
问题描述
[问题已解决。请参阅下面的答案。]
我刚刚遇到了一系列“重复键值违反唯一约束”的错误,该系统已经运行了几个月。我无法确定它们发生的原因。
这是错误:
org.springframework.dao.DuplicateKeyException: PreparedStatementCallback;
SQL [
INSERT INTO transaction_item
(transaction_group_id, transaction_type, start_time, end_time) VALUES
(?, ?::transaction_type_enum, ?, ?)
];
ERROR: duplicate key value violates unique constraint "transaction_item_pkey"
Detail: Key (transaction_id)=(67109) already exists.;
以下是相关 SEQUENCE 和 TABLE 的定义:
CREATE SEQUENCE transaction_id_seq AS bigint;
CREATE TABLE transaction_item (
transaction_id bigint PRIMARY KEY DEFAULT NEXTVAL('transaction_id_seq'),
transaction_group_id bigint NOT NULL,
transaction_type transaction_type_enum NOT NULL,
start_time timestamp NOT NULL,
end_time timestamp NOT NULL
);
这是用于插入该表的唯一 SQL 语句:
INSERT INTO transaction_item
(transaction_group_id, transaction_type, start_time, end_time) VALUES
(:transaction_group_id, :transaction_type::transaction_type_enum, :start_time, :end_time)
如您所见,我没有明确尝试设置 transaction_id 的值。我已经为列定义定义了一个默认值,并使用它从 SEQUENCE 中获取一个值。
我一直认为上述方法是安全的,即使在高并发情况下使用也是如此。一个 SEQUENCE 不应该两次返回相同的值,对吧?
我真的很感激一些帮助,以了解为什么会发生这种情况,以及如何解决它。谢谢!
解决方案
我找到了这个问题的原因。
几个月前(在这个系统的开发过程中)发现了一个问题,这意味着有必要从数据库中清除任何现有的测试数据。我对所有 TABLES 使用 DELETE FROM 语句,对所有 SEQUENCES 使用 ALTER ... RESTART 语句。这些语句已添加到 Liquibase 配置中,以便在新代码启动期间执行。从当时检查日志来看,系统的一个实例似乎在迁移时仍在运行。这发生了:系统的新实例删除了 TRANSACTION_ITEM 表中的所有数据,仍在运行的实例随后向该表添加了更多数据,然后新实例重新启动了用于插入这些记录的 SEQUENCE 使用。所以昨天,当我收到重复的密钥违规时,
说来话长,但现在一切都说得通了。感谢那些对此问题发表评论的人。
推荐阅读
- c++ - 如果我在整个班级上使用 std::swap 会使用专门的 shared_ptr::swap() 函数吗?
- javascript - 使用 Javascript 函数将数据传输到 C# webservice 并在 json 中获取返回失败
- javascript - Javascript根据选择更改多个div内容
- angular - 如何在不使用动态变量名称的 ngmodel 的情况下将 mat-slider 的值绑定到 angular 的 mat-input?
- node.js - 如何在 CentOS 6 上安装 libatk-bridge-2.0.so.0
- python - 在字符串中定义元组时,如何迭代元组以执行 2 个操作?
- windows - 如何找到显示谷歌驱动器同步刻度线的文件属性
- javascript - css 模块不能覆盖另一个 css 模块的样式
- php - preg_match 返回 1 虽然它不应该
- javascript - 通过 for 循环按部分 id 标签搜索元素