【发布时间】:2023-03-30 09:35:01
【问题描述】:
我们有一个奇怪的神秘数据损坏错误,每隔几周就会出现一次,没有人知道为什么。到目前为止,表上的主键似乎在自发地改变,所以指向它的其他行现在都乱了。
虽然我仍在寻找导致此问题的根本原因(无法重现),但我想要某种临时破解来防止列值发生变化。这是表架构:
CREATE TABLE TPM_INITIATIVES (
INITIATIVEID NUMBER NOT NULL,
NAME VARCHAR2(100) NOT NULL,
ACTIVE CHAR(1) NULL,
SORTORDER NUMBER NULL,
SHORTNAME VARCHAR2(100) NULL,
PROJECTTYPEID NUMBER NOT NULL,
CONSTRAINT TPM_INITIATIVES_PK PRIMARY KEY(INITIATIVEID)
NOT DEFERRABLE
VALIDATE
)
我们当然需要能够创建新行,但我想防止 ANYTHING 永远更改 INITIATIVEID,无论正在运行什么奇怪的查询。
我能想到的一些想法:
- 我对 Oracle 上的表权限不是很熟悉(我更 一个 Postgres 的人),但你不能授予或拒绝更新权限 某些列给所有用户?这只会影响更新,还是 也插入? DENY 更新此列的命令是什么?
- 创建某种在 ROW UPDATE 上运行的触发器。我们可以吗
检测
INITIATIVEID是否被更改,如果是,则抛出 异常或以某种方式爆炸?
至少,我们可以捕获和/或记录此事件以查看它何时发生以及导致INITIATIVEID 更改的查询是什么?
谢谢!
【问题讨论】:
-
还要注意创建重复行和删除旧行。
-
是的,我实际上注意到
INITIATIVEID上有一个 UNIQUE 约束,但有人禁用了它(?!?!) - 我已经开始重新启用它并验证它有效,所以希望这也能帮助这个错误消失。不过,我认为阻止对密钥的更新将解决这个问题。 -
哦,顺便说一句,插入新行的代码非常糟糕。它基本上会执行“SELECT MAX(INITIATIVEID) FROM INITIATIVES”并在其中添加 1 以获得新 ID。这完全不是交易安全的,而且真的很慢。这就是为什么我喜欢使用 UUID 作为密钥的原因,但现在这将是一个相当大的变化。
-
@MikeChristensen 您也许可以在
user_source中查询SELECT MAX(INITIATIVEID)并用序列替换它们.. -
是的,使用序列是可行的方法 - 但是,Oracle 不支持自动为表使用序列,我不知道如何让 .NET Entity Framework 使用序列插入。