13

背景:我正在开发一个系统,开发人员似乎正在使用一个执行 MYSQL 查询的函数,就像"SELECT MAX(id) AS id FROM TABLE"他们需要获取最后插入行的 id(具有 auto_increment 列的表)一样。

我知道这是一种可怕的做法(因为并发请求会弄乱记录),我正试图将其传达给非技术/管理团队,他们的回应是......

"Oh okay, we'll only face this problem when we have 
(a) a lot of users, or 
(b) it'll only happen when two people try doing something
    at _exactly_ the same time"

我不同意任何一点,并认为我们会比我们计划的更早遇到这个问题。但是,我正在尝试计算(或计算一种机制)来计算在我们开始看到混乱的链接之前应该有多少用户使用该系统。

对此有任何数学见解吗?同样,我知道这是一种可怕的做法,我只想了解这种情况下的变量......


更新:感谢大家的评论——我们正朝着正确的方向前进并修复了代码!

4

5 回答 5

5

关键不在于是否可能出现潜在的坏情况。关键是它们是否可能。只要问题发生的可能性很大,如果已知,就应该避免。

这不像我们在谈论将单行函数调用更改为 5000 行怪物来处理远程可能的边缘情况。我们正在谈论实际上将调用缩短为更易读、更正确的用法。

我有点同意@Mark Ba​​ker 的观点,即有一些性能考虑,但由于id是主键,MAX查询会非常快。当然,这LAST_INSERT_ID()会更快(因为它只是从会话变量中读取),但只是微不足道的数量。

而且您不需要很多用户就可以做到这一点。您所需要的只是大量并发请求(甚至没有那么多)。如果插入开始和选择开始之间的时间50 毫秒(假设事务安全的数据库引擎),那么您只需要每秒 20 个请求就可以开始始终如一地遇到问题。关键是错误的窗口很重要。如果您说每秒 20 个请求(实际上这并不多),并假设平均每个人每分钟访问一个页面,那么您只是在谈论 1200 个用户。这就是它定期发生的原因。只有 2 个用户可能会发生一次。

并从有关该主题的 MySQL 文档中

You can generate sequences without calling LAST_INSERT_ID(), but the utility of 
using the function this way is that the ID value is maintained in the server as 
the last automatically generated value. It is multi-user safe because multiple 
clients can issue the UPDATE statement and get their own sequence value with the
SELECT statement (or mysql_insert_id()), without affecting or being affected by 
other clients that generate their own sequence values.
于 2010-08-18T12:45:30.753 回答
2

而不是使用SELECT MAX(id)你应该做的文件说:

相反,在 SQL 查询中使用内部 MySQL SQL 函数 LAST_INSERT_ID()

即便如此, “线程安全”SELECT MAX(id)也不mysql_insert_id()是“线程安全”的,你仍然可能有竞争条件。您拥有的最佳选择是在您的请求之前和之后锁定表。甚至更好地使用事务。

于 2010-08-18T12:08:19.017 回答
0

我没有数学,但我会指出响应(a)有点愚蠢。公司不想要很多用户吗?这不是一个目标吗?这种反应意味着他们宁愿解决问题两次,第二次可能会付出巨大的代价,而不是第一次正确解决一次。

于 2010-08-18T12:10:34.900 回答
0

当有人在一个插入和该查询运行之间向表中添加了一些东西时,就会发生这种情况。因此,要回答您的问题,使用该系统的两个人有可能出现问题。

至少使用 LAST_INSERT_ID() 将获得特定资源的最后一个 ID,因此在两者之间添加了多少新条目无关紧要。

于 2010-08-18T12:10:50.523 回答
0

除了返回错误 ID 值的风险之外,还有额外的 SELECT MAX(id) 数据库查询开销,而且它实际执行的 PHP 代码比简单的 mysql_insert_id() 更多。为什么故意将某些东西编码为慢?

于 2010-08-18T12:34:44.350 回答