我有类似于Oracle的下表user_sequences。
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);
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,依此类推,不允许有空格。
foo
foo_number
到目前为止,如果我的应用程序在中运行,我们已经实现了自动递增逻辑single thread。我们foo_number将在foo表格中生成并填充其他数据点。
single thread
我只是简单地查询以获取下一个auto#。
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多次返回相同的结果。另外,由于应用程序端的限制和性能瓶颈,我无法在应用程序中强制执行单线程,因此需要在数据库端解决它。
select last_number from my_seq...
请提出建议,如何避免重复的数字?请帮助,在此先感谢。
我做了谷歌,很多stackoverflow链接建议get_last_id(),如您所见,我不能使用它。
get_last_id()
通过结合@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很重要。为了确保读取时有表级锁定,我将我的应用程序代码修改为:
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即使在有多个并发会话的情况下,这也可以产生唯一性。
sequence number
我遇到了另一个问题,该解决方案减慢了其他我生成序列号的地方。我已经解决了通过索引customer_id启用行级别锁而不是表级别锁的问题。
ALTER TABLE TABLE_NAME ADD INDEX (customer_id);
希望这对其他人有帮助。