我正在研究一些旧产品,他们正在使用一个表为每个表生成唯一键(主键)。该表包含所有其他表的最新ID。当他们想在任何其他表中插入一行时,以下是他们用来为该新行生成唯一ID的逻辑
用于生成密钥的表看起来像
ID | NEXT_ID | TABLE_NAME
public synchronized long generateKey(Connection con){
// select the latest ID value from the table against a row
// increment the value by 1
// update the table with this latest value
// return the latest value
}
在单节点线程环境中,一切正常。但是在集群环境中执行上述逻辑时,需要进行更改以获取竞争条件。因此,为了解决这个问题,我们考虑使用一个Java函数来调用执行上述工作的PL / SQL函数。代码如下
public long generateKey(Connection con) {
// call PL/SQL function and return the value
}
以下是PL / SQL函数的框架
FUNCTION GET_NEXT_ID(tablename IN VARCHAR2)
RETURN NUMBER IS
PRAGMA AUTONOMOUS_TRANSACTION;
nextID NUMBER;
BEGIN
SELECT NEXT_ID INTO nextID FROM <Key_generator_table> WHERE TABLE_NAME=tablename FOR UPDATE;
UPDATE <Key_generator_table> SET NEXT_ID=NEXT_ID+1 WHERE TABLE_NAME=tablename;
commit;
RETURN (nextID);
END;
我对SELECT FOR UPDATE的了解是,它在我们检索时锁定行,以便在尝试更新记录时没有其他事务可以看到。因此,它在非集群环境中适用。我的问题是,在集群环境中,同样适用吗?这种方法会不会有比赛条件?
很遗憾,由于产品的限制,我们无法更改唯一ID生成方法。
答案 0 :(得分:0)
这将序列化您的交易。不是一个好的设计。在您的PL / SQL函数中有序列并从中获取值怎么样?