【发布时间】:2014-07-09 16:04:26
【问题描述】:
在我完成之前阻止其他会话读取数据
我有一张桌子可以容纳来自不同公司的客户,例如:
CUSTOMER
CUSTOMER_ID
COMPANY_ID
CUSTOMER_NAME
FOO_CODE
当我插入或更新客户时,我需要根据现有客户(公司内部)计算 FOO_CODE。
如果我只是这样做:
SELECT MAX(FOO_CODE) AS GREATEST_CODE_SO_FAR
FROM CUSTOMER
WHERE COMPANY_ID=:company_id
...然后以客户端语言 (PHP) 生成代码,最后发出 INSERT/UPDATE 我知道如果其他程序实例获取相同的GREATEST_CODE_SO_FAR,我可能会面临竞争条件。
是否可以在表上发出行级锁定,以便尝试读取属于给定公司的任何客户的FOO_CODE 列的其他会话被延迟,直到我提交或回滚我的事务?
我的失败尝试:
-
这个:
SELECT MAX(FOO_CODE) FROM CUSTOMER WHERE COMPANY_ID=:company_id FOR UPDATE...触发器:
ORA-01786: 不允许对此查询表达式进行 FOR UPDATE
-
这个:
SELECT FOO_CODE FROM CUSTOMER WHERE COMPANY_ID=:company_id FOR UPDATE...检索所有公司行,甚至不阻止其他会话读取数据。
LOCK TABLE...好吧,文档几乎没有任何示例,我无法弄清楚语法
附: 不是一个递增的数字吗,它是一个字母数字字符串。
【问题讨论】:
-
你有 FOO_CODE 字段的唯一键吗?它可以防止在此列中具有相同的值。如果您有竞争条件,您将根据需要正确插入值多次重新启动程序。使用唯一密钥的解决方案也将扩大规模,因此您不会有不必要的锁和闩锁。
-
@zaratustra - 我没有,但无论我接下来做什么,我都需要修复一个明显的遗漏。
-
另外,如果你不向用户显示这个字段,你可以使用函数
SYS_GUID()生成FOO_CODE,它非常可靠,即使在具有RAC架构的系统中也可以使用它