Creating JVM level and Thread Safe Sequence in DB

时间:2017-08-04 12:53:41

标签: sql stored-procedures sybase sequences

It is old question but to be sure i am asking again. Actually i have created sequence like in Oracle with a table and want to use with multiple threads and multiple JVM's all process will be hitting it parallel.

Following is sequence stored procedure just want to ask whether this will work with multiple JVM's and always provide unique number to threads in all jvm's or is there any slight chance of it returning same sequence number two more than one calls?

create table sequenceTable (id int)
insert into sequenceTable values (0)

create procedure mySequence 
AS
BEGIN
    declare @seqNum int
    declare @rowCount int

    select @rowCount = 0
    while(@rowCount = 0)
    begin
        select @seqNum = id from sequenceTable
        update sequenceTable set id = id + 1 where id = @seqNum
        select @rowCount = @@rowcount
        print 'numbers of rows update %1!', @rowCount
    end
    SELECT @seqNum
END

2 个答案:

答案 0 :(得分:1)

您可以在ASE中模拟序列。使用reserve_identity功能来实现所需的活动类型:

create table sequenceTable (id bigint identity)
go

create procedure mySequence AS
begin
    select reserve_identity('sequenceTable', 1)
end
go

此解决方案是非阻塞的,并且确实生成最少的事务日志活动。

答案 1 :(得分:1)

如果您选择在每次要生成新序列号时保持当前更新SELECT id FROM questions WHERE id in ( SELECT question_id FROM answers GROUP BY question_id ORDER BY COUNT(CASE WHEN [NOT] was_correct THEN 1 END) <-- DESC LIMIT 1) 列的设计,则需要确保:

  • &#39;当前&#39;进程获取包含所需序列号的行的独占锁定
  • &#39;当前&#39;然后,进程更新所需的行并检索新更新的值
  • &#39;当前&#39;进程释放独占锁

虽然以上内容可以通过sequenceTable.id + begin tran + update + select来实现,但实际上只需{{1}就可以轻松实现声明,例如:

commit tran

update语句是其自己的事务,因此create procedure mySequence AS begin declare @seqNum int update sequenceTable set @seqNum = id + 1, id = id + 1 select @seqNum end 列的更新和update的分配是在id&#39内的排他锁下执行的; s transaction。

请记住,独占锁会阻止其他进程获取新的id值;最终结果是新id值的生成将是单线程/顺序

虽然这很好[&#39;从确保所有进程获得唯一值的角度来看,如果您有多个进程同时点击@seqNum = id + 1,则表示这个特定的update语句会成为瓶颈。

在这种情况下(大量并发update s)你可以通过较少调用存储过程来缓解一些争用;这可以通过让调用进程请求一系列新的id值(例如,将update作为输入参数传递给proc,而不是update使用@increment)来实现,调用过程然后知道它可以使用序列号(id + 1)到id + @increment

显然(?)任何使用存储过程来生成下一个id&#39;值仅在 * ALL * 处理a)时始终调用proc以获取新的id值,并且b) * ALL * 进程仅使用proc返回的id值(例如,他们不会生成自己的id值。

如果应用程序没有遵循此过程的可能性(调用proc获取新的id值),您可能需要考虑将创建唯一的id值推出到插入这些id值的表中;换句话说,修改目标表的id列以包含@seqNum-@increment+1属性;这消除了应用程序调用存储过程(生成新id)的需要,它(仍然)确保为每个插入生成唯一的id。