通过尝试插入来测试MYSQL中的重复记录
我在写一个将用户插入MYSQL表的函数。最初我写了这样一个功能,它首先会用SELECT
声明检查具有相同用户名的现有用户。但是,我的表指定用户名列是唯一的,所以我意识到在检查用户是否存在后,数据库会再次检查。通过尝试插入来测试MYSQL中的重复记录
只是尝试插入该行并查看是否有错误或者是否明确地检查了SELECT
语句会更好吗?
不知道很多关于你的环境,编程语言,负载,性能等我要说坚持什么让你感觉良好!
这两种情况都没有错;)
想想并编写常见的场景。我的意思是,你是说这是为新的注册用户。那么,你认为用户会多频繁地尝试重新注册?对!我会在这种情况下尝试插入第一种情况。
您是否认为您的插入失败率很高,那么首先进行选择检查是很好的。
如果这是基于Web的应用程序,我会通过Ajax请求执行检查以获得更好的最终用户体验。
我打算这样做,但问题是关于在后端创建用户功能 – bytesized
如果您已验证您的dB,用户名不存在允许用户提交表单。否则,请不要提交表单,以便每个用户名只提供一次dB检查。我不认为有必要采取另一项安全措施。 –
您正在寻找INSERT IGNORE。在重复主键插入时,它将生成警告而不是错误,并且您不需要运行SELECT来检查重复项。
阅读了一下你链接到的文档后,这听起来就像我想要的相反。这不妨碍我想用来检测重复的用户名的确切错误吗?看起来这样会导致服务器显示“全部完成,您的用户名现在存在”,实际上什么都没有完成。 – bytesized
这取决于你如何做检查。
当你在insert
之前做select
时,你有一个竞争条件。另一个用户/线程可以在,select
和insert
之间插入重复记录。这就是为什么你想要在insert
做检查。
通常,在insert
中进行检查就足够了。如果您想避免该错误,请使用on duplicate key update
。这比insert ignore
更可取,因为on duplicate key update
只能处理有关密钥重复的错误。 Insert ignore
忽略所有错误。
我会说,除非你有某些特殊的原因,否则不要打扰手边的检查。原因如下:
- 想要最小化表被锁定的时间,因此您希望避免提出问题,例如“发生重复时表锁定多长时间?”。
- auto_increment列中的故意漏洞会打扰您(实际上,我不确定这是MySQL的问题)。
- 您插入多行,并希望能够检测多个重复报告给用户。
如果我预期失败率很高,难道我不想避免额外支票来摆脱开销吗? – bytesized
在这种情况下(比db引擎中的错误处理成本更高),对高速插入失败进行选择检查的代价将更容易。所有都可以测量,你可以设置一个负载并运行这两种方案来查看你的数据库引擎行为。如上所述,如果您正在寻找性能增益的常见场景代码 – MrSimpleMind
有趣。我没有意识到在数据库引擎中的错误处理会有很大的开销(我猜这是有道理的)。但是,最终,我打算所有的验证都通过客户端完成(在这种情况下通过AJAX)。因此,我预计失败率很低,所以我认为我会先插入,然后再提问。 – bytesized