您可以在ASE中模拟序列。使用 reserve_identity 功能,以实现所需的活动类型:
reserve_identity
create table sequenceTable (id bigint identity) go create procedure mySequence AS begin select reserve_identity('sequenceTable', 1) end go
此解决方案是非阻塞的,并且确实生成最少的事务日志活动。
如果您选择保持当前的更新设计 sequenceTable.id 列每次要生成新的序列号时,您需要确保:
sequenceTable.id
虽然以上可以通过实现 begin tran + update + select + commit tran ,单身实际上要容易一些 update 声明,例如:
begin tran
update
select
commit tran
create procedure mySequence AS begin declare @seqNum int update sequenceTable set @seqNum = id + 1, id = id + 1 select @seqNum end
该 update 声明是它自己的事务所以更新了 id 列和分配 @seqNum = id + 1 是在一个独家锁定下进行的 update 的交易。
id
@seqNum = id + 1
请记住,独占锁将阻止其他进程获取新的id值;最终结果是新id值的生成将是单线程/顺序的
虽然从确保所有流程获得独特价值的角度来看这是“好的”,但它确实意味着这一点 update 如果你有多个进程命中,语句就成了瓶颈 update 同时。
在这种情况下(并发数量很大) update s)你可以通过减少调用存储过程来减轻一些争用;这可以通过让调用进程请求一系列新的id值(例如,传递)来实现 @increment 作为proc的输入参数,然后代替 id + 1 你用 id + @increment ),通过调用过程然后知道它可以使用序列号( @seqNum-@increment+1 ) 至 @seqNum 。
@increment
id + 1
id + @increment
@seqNum-@increment+1
@seqNum
显然(?)使用存储过程来生成“下一个id”值的任何进程仅在以下情况下有效 的 *所有* 强> 进程a)总是调用proc获取新的id值和b) 的 *所有* 强> 进程只使用proc返回的id值(例如,它们不生成自己的id值)。
如果应用程序有可能不遵循此过程(调用proc获取新的id值),您可能需要考虑将唯一id值的创建推送到插入这些id值的表中;换句话说,修改目标表的id列以包含 identity 属性;这消除了应用程序调用存储过程(生成新id)的需要,它(仍然)确保为每个插入生成唯一的id。
identity