也许这是一个愚蠢的问题,因为我应该将PK增量推迟到MySql本身,但我处于一种奇怪的情况。
基本上,为了处理我的系统中的版本控制和批准,我有revision_batch
表,它是用户希望插入或更新到数据库的提交内容的集合。它包含batch_id
,提交者的user_id
和approved
值等列。
它也是revisions
表中项目集合的父级。修订表包含table_name
,key
,old_value
和new_value
等内容。我使用它来存储某些人希望自动生成的更改。
当某人没有获得许可时,例如,"任务"表,并且他们更改了任务的名称,将创建新的revision_batch
,并使用revision
="任务",{创建新的table_name
{1}} = [无论任务的ID是什么],key
="我的旧任务名称",old_value
="我的新任务名称&# 34 ;.
当审批者批准此批处理时,我的代码将浏览批处理中的修订并执行更新或插入数据库。
我的问题是在同一批次中执行父子关系。如果我正在创建一个新的new_value
,并希望在同一批次中为其分配一个task
,那么我需要知道task_item
获得的PK是什么,以便我可以给task
一个" task_item
"。
如果我正在为task_id
处理新revision
的创建,我可能会做类似
task
注入新id。但是,由于我可能已经有一个挂起的任务插入具有该ID或更高的ID,我也检查
select max(id)+1 as newId from tasks
要分配更高的ID。我在select max(key) + 1 as newId
from revisions
inner join revision_batches on revisions.batch_id = revision_batches.id
where table_name='revisions' and approved = 'P'
表中使用了ids 1-9,在tasks
表中有10-12个待定,使用Laravel的Eloquent模型类的任何新直接插入都被覆盖以检查这两个任务和修订,并将插入id 13.这可以避免实际的粘合行和可能的修订行之间的冲突。它还允许我在一个批次中创建一个父级和多个子级层,因为我一直在确定它们的ID。
这一切都很好。
我的问题是,如果我在同一时间发生了两次revisions
创作(例如,在一毫秒内),他们异步地同时获取要使用的相同下一个ID,两者都创建修订版本key =相同的数字,然后只有一个会通过而另一个在PK冲突时失败。
我的问题是:有没有办法强制它是线程安全的或同步完成,以避免同一个控制器方法的两个实例同时执行并同时获取相同的ID?我可以一次将方法锁定到单个实例吗?如果没有,是否有更好的方法来处理PK生成?我这样做的唯一原因是事先知道要插入的密钥。但由于框架中的自定义代码是处理PK生成而不是数据库,因此它导致了这个主要问题。偶尔会发生,但只有当我强迫同一个方法同时执行4次时才会发生。
我知道我可以避免大多数情况下我在同一时间插入很多东西,但这并不意味着将来两个用户不会随意输入同时重新创造这个问题。
有什么想法吗?
谢谢!
答案 0 :(得分:2)
对于这类问题,我使用UUID 4,(Universally unique identifier),我的情况略有不同,因为我在74个不同的位置有一个系统,但是需要提取所有的交易记录并集成在一个整合系统,因此我的PK需要在所有服务器上都是唯一的,以避免冲突。
在laravel中,我使用this excelent package生成UUID
我希望这适合你。
答案 1 :(得分:1)