【发布时间】:2015-06-28 01:04:14
【问题描述】:
也许这是一个愚蠢的问题,因为我应该将 PK 增量推迟到 MySql 本身,但我的情况很奇怪。
基本上为了在我的系统中处理版本控制和批准,我有revision_batch 表,它是用户希望插入或更新到数据库的提交中的东西的集合。它具有batch_id、提交者的user_id 和approved 值等列。
它也是revisions 表中项目集合的父级。修订表包含 table_name、key、old_value 和 new_value 之类的内容。我使用它来存储某人希望进行的可能不会自动批准的更改。
当某人无权访问“任务”表时,他们更改了任务的名称,将创建一个新的revision_batch,并使用@ 创建一个新的revision 987654332@="tasks", key=[无论任务 ID 是什么], old_value="我的旧任务名称", new_value="我的新任务名称"。
当批准者批准此批次时,我的代码将快速浏览批次中的修订并执行更新或插入数据库。
我的问题是在同一批次中执行父子关系时。如果我正在创建一个新的task 并想在同一批次中为其分配一个task_item,那么我需要知道task 得到了什么PK,以便我可以给task_item 一个“ task_id"。
如果我要为task 创建一个新的revision,我可能会做类似的事情
select max(id)+1 as newId from tasks
作为新的 id 注入。但由于我可能已经有一个具有该 ID 或更高 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'
用于分配更高的 id。这样,我在 tasks 表中有 id 1-9,在 revisions 表中有 10-12 待处理,使用 Laravel 的 Eloquent 模型类的任何新直接插入都将被覆盖以检查任务和修订,并将插入 id 13 . 这避免了实际粘合行和可能的修订行之间的冲突。它还允许我在单个批次中创建父级和多个子级,因为我会在执行过程中确定他们的 ID。
这一切都很好。
我的问题是,如果我有两个 revisions 同时发生(例如,在一毫秒内),它们将异步获取相同的下一个 ID 以使用,两者都创建 key = 相同的修订编号,然后只有一个会通过,另一个会在PK冲突时失败。
我的问题是:有没有办法强制它是线程安全的或同步完成,以避免同一控制器方法的两个实例同时执行并且都获取相同的 ID 来使用?我可以一次将一个方法锁定到一个实例吗?如果没有,有没有更好的方法可以处理 PK 生成?我这样做的唯一原因是事先知道要插入的密钥。但是由于框架中的自定义代码是处理 PK 生成而不是数据库,这给我带来了这个主要问题。偶尔会发生,但只有当我强制同一方法同时执行 4 次时才会发生。
我知道我可以避免同时插入许多东西的大多数情况,但这并不意味着将来随机两个用户不会同时按 enter 并且重新创建此问题。
有什么想法吗?
谢谢!
【问题讨论】:
标签: php mysql laravel laravel-4 eloquent