我正在使用PHP / MySQL。检查用户名是否已被采用的最佳方法是什么?
现在我所做的就是执行一个select语句,看看是否已经使用了用户名。如果select返回一行,则我停止并显示错误消息。如果select没有返回任何内容,那么我插入新用户。
但是有更有效的方法吗?例如,我可以在用户名列上使用UNIQUE,然后只执行一个insert语句(如果已经使用了插入语句,则从插件中获取错误)。
答案 0 :(得分:5)
您确实存在其他一些线程会在您确认用户不存在的SELECT和插入它的INSERT之间的短暂时间内插入您的用户名的风险。这称为race condition。
似乎发生这种情况的可能性很小,但有一种说法:“One in a million is next Tuesday.”
是的,用户名上的UNIQUE约束可以阻止您插入重复的用户名。声明那个约束。
有些文章会告诉您,一旦有了UNIQUE约束,就不必再进行SELECT了。只需尝试 INSERT,如果冲突,则报告错误。
但是,我帮助网站从这种技术引起的问题中恢复过来。用户在他们的网站上试图非常快速地创建新的用户名,并导致INSERT上出现很多冲突。问题是MySQL increments the auto-increment primary key for the table, even if the INSERT was canceled。并且这些自动增量值永远不会被重用。结果是他们为每个成功的INSERT丢失了1000-1500个id号。当他们的INT主键达到2 31 -1时,他们打电话给我,他们无法在表中创建另一行!
他们使用的解决方案是首先尝试SELECT,并报告重复。然后,如果它似乎安全,请尝试INSERT - 但是编写代码来处理与UNIQUE约束的可能冲突,因为竞争条件仍然可能发生。