如何保证我可以搜索数据库中是否存在用户名,然后将该用户名作为新行插入数据库中,而在用户名之间没有任何拦截SELECT
and INSERT
声明?
几乎就好像我锁定了不存在的行。我想用用户名锁定不存在的行"Foo",这样我现在就可以检查它是否存在于数据库中,如果不存在,则将其插入数据库,而不会造成任何中断。
我知道使用LOCK IN SHARE MODE
and FOR UPDATE
存在,但据我所知,这只适用于已经存在的行。我不知道在这种情况下该怎么办。
虽然上面的答案是正确的,因为 SELECT ... FOR UPDATE 将阻止并发会话/事务插入相同的记录,但这并不是全部事实。我目前正在与同样的问题作斗争,并得出结论,在这种情况下 SELECT ... FOR UPDATE 几乎没有用,原因如下:
并发事务/会话也可以对同一个记录/索引值执行 SELECT ... FOR UPDATE,MySQL 会很乐意立即接受(非阻塞)并且不会抛出错误。当然,一旦其他会话完成此操作,您的会话也无法再插入记录。您或其他会话/事务都不会获取有关情况的任何信息,并认为他们可以安全地插入记录,直到他们真正尝试这样做。尝试插入 then 会导致死锁或重复键错误,具体取决于具体情况。
换句话说, SELECT ... FOR UPDATE 会阻止其他会话插入相应的记录,但即使您执行 SELECT ... FOR UPDATE 并且未找到相应的记录,您也可能实际上无法插入该记录。恕我直言,这使得“先查询,然后插入”方法毫无用处。
问题的原因是MySQL没有提供任何方法really锁定不存在的记录。两个并发会话/事务可以同时锁定不存在的记录“用于更新”,这实际上不应该是可能的,并且这使得开发变得更加困难。
解决这个问题的唯一方法似乎是使用信号量表或在插入时锁定整个表。请参阅 MySQL 文档以获取有关锁定整个表或使用信号量表的更多参考。
只是我的2分钱...
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)