Heroku PostgreSQL:重启添加重复行
Posted
技术标签:
【中文标题】Heroku PostgreSQL:重启添加重复行【英文标题】:Heroku PostgreSQL: Restart adds duplicate lines 【发布时间】:2020-02-23 01:16:22 【问题描述】:我有一个使用 PostgreSQL 插件在 Heroku 上运行的 Spring Boot 应用程序。在启动时,spring boot 会自动在 PostgreSQL 中创建一些虚拟数据,例如 users 及其联系信息。表和insert语句存储在Schema.sql
(pastebin)和Data.sql
(pastebin)中
第一次启动时一切正常,但在我重新启动后,spring boot 应用程序再次创建相同的行,这会导致出现重复行、重复关系等错误。
如何在重启时禁用数据娱乐?
Heroku Config Vars 设置为:
每个 SQL 插入语句都有 ON CONFLICT DO NOTHING,每个创建表语句都有 IF NOT EXISTS
【问题讨论】:
“在启动时 spring boot 会自动创建一些虚拟数据”——你为什么在你的应用程序启动时这样做? @Chris 因为我希望在启动时存在一些数据。当应用程序在使用时,它基本上可以让人们看到一切看起来如何。 对,但为什么应用程序启动?将其作为部署的一部分,或者更好的是,通过运行脚本明确地播种它不是更有意义吗?这听起来像是一次性任务,而不是每天都应该发生的事情(Heroku dynos 经常重启)。或者,根据数据,它可能属于数据库迁移。 @Chris 我希望应用程序启动时数据始终相同。这样,当参与者在那里添加他们自己的东西时,它会在 Dyno 重新启动时的某个时间点被删除。重点是显示“起始”数据,并且每次重新启动后起始数据都应该始终存在。即使用户决定搞砸它。 【参考方案1】:虽然@richyen 已正确识别问题,但我会建议一个不同的解决方案:修复您的架构并为您的用户使用natural keys,而不是(或至少除了)surrogate serial
key。
CREATE TABLE IF NOT EXISTS users(
id SERIAL PRIMARY KEY,
username varchar(255) UNIQUE NOT NULL,
-- ^^^^^^
email varchar(255) UNIQUE NOT NULL,
-- ^^^^^^
PASSWORD varchar(255) NOT NULL,
enabled INTEGER DEFAULT 0,
created_at TIMESTAMP,
modified_at TIMESTAMP,
removed_at TIMESTAMP
);
(A PRIMARY KEY
与 UNIQUE NOT NULL
完全相同,只是你只能拥有它一次,并且它成为对未显式指定列的表的外键引用的默认值).
当您尝试插入具有相同姓名或电子邮件地址的用户时,这将导致预期的冲突。
【讨论】:
我按照你@Bergi 所说的做了,它就像richyen 所说的那样工作。我对这两个答案都投了赞成票,并选择了这个作为答案,因为它解决了我的问题。 这是一个很好的观点——对“重要的事情”的独特限制。我一定会把它添加到我的建议清单中:D【参考方案2】:这里的问题是,即使您指定了ON CONFLICT DO NOTHING
,您也没有在您的INSERT
语句中指定id
列。这不一定是坏事,但基本上它会使您的 ON CONFLICT DO NOTHING
子句无效(至少为了启动顺序)。您将永远不会遇到冲突,因为id
列是一个序列并且它是您的主键。因此,如果您没有在INSERT
语句中明确命名它,数据库将很高兴地添加另一行,该行具有该id
序列的“下一个”值,以及在您的INSERT
中命名的其他列。只有当您遇到主键有两个相同值的情况时才会发生冲突,而在您的 Data.sql
中,您永远不会遇到这种情况。
如果您真的想要ON CONFLICT DO NOTHING
行为,那么您需要在您的INSERT
s 中添加一个id
列,然后确保将您的序列设置为setval()
,以便您生成的新行应用程序不会因为id
冲突而无意中删除/忽略。
另一个选项(如果您的数据集仅用于开发)是截断您的表,以便您每次都能获得干净的工作数据集(但这取决于您的要求)。如果您这样做,那么您还需要重置您的序列,这样您的id
s 就不会永远保持增长。
最后,既然您已经加载了种子数据,您就可以设置SPRING_DATASOURCE_INITIALIZATION_MODE = Never
。同样,这只是您需要根据您的要求做出的决定。
【讨论】:
以上是关于Heroku PostgreSQL:重启添加重复行的主要内容,如果未能解决你的问题,请参考以下文章
Heroku 和 Django 组合中的 Postgresql 更改与共享数据库
Heroku上的现有Ruby on Rails Web应用程序(PostgreSQL),Devise身份验证,需要为移动支持添加Rails API