简体   繁体   English

MySQL SELECT返回旧值

[英]MySQL SELECT returning old value

I have a application that unfortunately uses legacy mysql_* functions with MyISAM tables (bleagh...), so I cannot use transactions. 我有一个应用程序,不幸的是将旧版mysql_ *函数与MyISAM表一起使用(问题...),因此我无法使用事务。 I have code that gets a current balance, checks whether this balance is okay, if yes, it will subtract a quantity and save the new balance. 我有获取当前余额的代码,检查此余额是否还可以,如果可以,它将减去一个数量并保存新余额。

The problem is, I have recently seen an instance where two queries grab the same starting balance, subtract a quantity, then record a new balance. 问题是,我最近看到一个实例,其中两个查询获取相同的起始余额,减去一个数量,然后记录一个新的余额。 Since they both grabbed the same starting balance, the ending balance after both UPDATES is wrong. 由于它们都抓住了相同的开始余额,因此两次UPDATES之后的结束余额都是错误的。

100 - 10 = 90
100 - 15 = 85

When it should be... 什么时候应该...

100 - 10 = 90
90 - 15 = 75

These requests executed a several minutes apart, so I do not believe the discrepancy is due to race conditions. 这些请求每隔几分钟执行一次,因此我不认为差异是由于比赛条件造成的。 My initial though is that MySQL cache is storing the result of the identical initial query that gets the balance. 我最初的想法是,MySQL缓存正在存储获得余额的相同初始查询的结果。 I read however that this type of cache is deleted if any relevant tables are modified. 但是,我读到,如果修改了任何相关表,就会删除这种类型的缓存。

I will most likely fix by putting everything into one query, but I still would like to figure this out. 我很可能会通过将所有内容放入一个查询中来解决问题,但我仍然想弄清楚这一点。 It mystifies me. 它使我迷惑。 If cache is deleted when a table is modified, then what happened shouldn't have happened. 如果在修改表时删除了缓存,那么发生的事情就不应该发生。 Has anyone heard of something like this, or have any ideas as to why it may have happened? 有没有人听说过这样的事情,或者对为什么会发生这样的事情有任何想法?

It's highly unlikely to be a query cache - MySQL is smart enough to invalidate a cache entry if the underlying data set has been modified by another query. 几乎不可能是查询缓存-如果基础数据集已被另一个查询修改,MySQL足够聪明,可以使缓存条目无效。 If the query cache kept around old stale values long past their expiration, MySQL would be utterly useless. 如果查询缓存在过期之前仍旧保持旧的过时的值,那么MySQL将毫无用处。

Do you perhaps have outstanding uncommitted transactions causing this? 您是否可能有未完成的未提交交易导致了这一情况? Without the appropriate locks on the relevant records, your second query could be grabbing stale data quite easily. 在相关记录上没有适当的锁定,您的第二个查询可能很容易捕获过时的数据。

Most likely your application has stale data. 您的应用程序很可能具有过时的数据。 This is fine, it's how many database applications work, but when you perform your update, instead of doing something like this: 很好,这是有多少个数据库应用程序可以工作,但是当您执行更新时,不要这样做:

UPDATE account
SET balance = :current_balance - 10
WHERE account_id = 1

You need to do something more like this: 您需要执行以下操作:

UPDATE account
SET balance = balance - 10
WHERE account_id = 1

That way, you use the current balance from the database, even if somebody changed it in the mean time, instead of relying on stale application data. 这样,即使有人同时更改数据库中的当前余额,您也可以使用它,而不是依靠过时的应用程序数据。

If you want to only change the value if no one else has modified it, then you do something like this: 如果您只想在没有其他人修改它的情况下更改该值,则可以执行以下操作:

UPDATE account
SET balance = balance - 10
WHERE account_id = 1
  AND balance = :current_balance

If the number of affected rows is 1, then you succeeded, the record hadn't changed by someone else. 如果受影响的行数为1,则说明您成功了,但记录没有被其他人更改。 However, if the number of affected rows is 0, then somebody else changed the record. 但是,如果受影响的行数为0,则其他人更改了该记录。 You can then decide what you want to do from there. 然后,您可以从那里决定要做什么。

我认为锁定表是解决您的问题的方法:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM