Oracle中的Oracle序列等效

时间:2018-06-13 07:56:30

标签: mysql sql database sequences

我有以下类似于Oracle user_sequences的表。

我有序列前缀/后缀的逻辑,但为了简单起见,我在这里少跳过。

create table my_seq(
min_value integer,
Max_value integer,
last_value integer,
increment_by tinyint,
customer_id integer);

假设在当前表中有两条记录。

insert into my_seq(min_value,max_value,last_value,increment_by,customer_id) 
  values(1,99999999,1,1,'foo#',1),(1,999999999,100,1,'foo#',2);

我的foo表结构就像,

create table foo(id Auto_increment,foo_number varchar(20),customer_id integer);

约束: 我不能使用MySQL AUTO_INCREMENT列,因为foo包含不同的客户数据,并且每个客户都可以选择foo_number自动生成或手动输入,如果客户选择了auto_generation,则应该存在差距。所以customer = 1选择了它,foo#应该是1,2,3,4等,不允许有间隙。

到目前为止,如果我的应用程序在single thread中运行,我们已经实现了自动增量逻辑。我们生成foo_number并填入foo表以及其他数据点。

我只是进行查询以获得下一个自动#。

select last_number from my_seq where customer_id=?;

读取#并更新记录。

update my_seq set last_number=last_number+increment_by where customer_id=?;

问题: 当多个并发会话尝试运行select last_number from my_seq...时,它会多次返回相同的foo_number。另外,由于应用程序端限制和性能瓶颈,我无法在应用程序中强制执行单线程,因此需要在数据库端解决它。

请建议,我如何避免重复的数字?请提前帮助,谢谢。

我确实谷歌,许多stackoverflow链接建议get_last_id(),你可以看到,我不能使用它。

1 个答案:

答案 0 :(得分:0)

我能够通过结合@Akina和@RickJames的建议来解决这个问题,谢谢你们的支持。

create table my_seq(
min_value integer,
Max_value integer,
last_value integer,
increment_by tinyint,
customer_id integer)ENGINE = InnoDB;

这里ENGINE=InnoDB非常重要。 为了确保在阅读时有表级锁定,我已将我的应用代码修改为:

Auto-Commit=FALSE

然后,

//very import to begin the transaction
begin;
select last_number from my_seq where customer_id=? FOR UPDATE;

Read the result in App.

update my_seq set last_number=last_number+1 where customer_id=?;
commit;

即使在多个并发会话的情况下,这也会生成唯一的sequence number

我遇到了另一个问题,这个解决方案已经放慢了其他我生成序列#的地方。我已经解决了它通过索引customer_id来启用行级锁定而不是表级锁定。

ALTER TABLE TABLE_NAME ADD INDEX (customer_id);

希望这对其他人有所帮助。