【发布时间】:2015-04-06 20:23:58
【问题描述】:
假设我有以下情况:一个用户只能执行一项活动任务。
因此,如果我想为 id 为 2 的用户添加任务,我需要这样做:
SELECT * FROM tasks WHERE active=1 AND id_user = 2;
如果没有记录我可以做
INSERT INTO tasks(id_user, active) VALUES(2,1);
问题是:如果我将 select 和 insert 放入事务中(并使用 InnoDB),我可以确定用户不会创建 2 个活动任务吗?
上面的情况被简化了,但是我被告知在 MySQL 备份期间(mysql 插入被服务器以某种方式排队)用户创建了许多不允许使用这样的代码的活动任务(我目前不知道事务是否用过的)。根据“故事”,唯一可行的解决方案是使用队列(可能是 Beanstalkd)在完成另一个任务后执行运行任务。
所以问题是 - 是否有可能发生这样的事情,如果使用 MySQL 事务将是有效的解决方案,或者在这种情况下应该使用其他解决方案吗?
编辑
这里的问题是我不能为列添加唯一键,我也不能更新记录。只是为了更准确,真实情况是:
在表格任务中有:
id - 主键,自动递增 id_user - 用户 ID 开始日期 end_date - 可为空(如果任务未完成,则设置为空)
一个用户只能有一个未完成的任务(end_date 为空),因此当用户至少有一个日期为空的任务时,无法为该用户创建新任务。但是,我在旧数据库上操作,如果 end_date 设置为 null,很可能会有许多相同用途的记录,所以我不能在这里使用唯一的,每次插入之前我都需要先检查
SELECT * FROM tasks WHERE end_date IS NOT null AND id_user = 2
如果没有记录,那么我可以为用户创建新任务。
也很有可能在未来添加更多此选择的条件以在创建新任务之前进行验证。
【问题讨论】:
标签: mysql sql transactions innodb race-condition