MySQL选择更新,以确保行/值只使用一次?

时间:2017-07-25 20:36:21

标签: mysql

从我的阅读中我相信SELECT FOR UPDATE将用于完成以下操作,但我读了类似于“行锁定不会停止读取”的注释,这让我觉得我错过了一些东西。原谅我的伪代码。

table 'first_names'

`name`   `used`
mike     1
jeff     null
mark     null

我需要从这个表中获取一个名称,但绝对100%确保它以前从未使用过,并且不会被其他任何东西使用。 (一个假的例子,假设我们自动分配用户名 - 当有人在我们的网站上创建一个帐户时必须是唯一的)为了实现这一点,当我从这个表中获取/使用一个名字时,我们设置used = 1。

但问题当然是两个独立的进程select where used <> 1如果进程#1在进程#2运行update used = 1之前没有select where used <> 1,则可以获得“jeff”。

在事务中SELECT FOR UPDATE是否解决了这个问题?我知道它会锁定行,以便另一个进程不能到该行,但我们正在进行读取,选择。含义进程#1和进程#2同时运行select where null <> 1,因此得到相同的行(jeff)。进程#1写入行update used = 1,释放锁,现在进程#2也写入行....现在行jeff已被使用了两次。

1 个答案:

答案 0 :(得分:1)

另一种方法是拥有日志/事务表。

 NameUsed
----------
 Mike

首先检查名称是否已被使用

select count(*) from log where nameused='jeff'

这会返回&#39; 0&#39;对于这两个进程,相对确定该名称是免费的两个进程运行:

Insert into log (NameUsed) values('jeff');

诀窍是NameUsedUNIQUE列,您的DBMS只允许您的某个进程成功插入名称,其中一个将失败,并且必须是唯一的&#39;这比其他用户锁定更有帮助&#39;。

此方法可优化写入速度并最大限度地减少主表的锁定。

检查名称是否已被使用但速度稍慢,但使用正确的索引并不多。