【发布时间】:2011-12-30 03:00:11
【问题描述】:
此处需要快速提问/澄清。我有一个数据库表,很可能同时更新记录。我正在为应用程序使用 Zend Framework,并且我已经阅读了避免这种情况的两个方向,首先是表锁定(LOCK TABLES test WRITE)或类似的东西,将返回并重新阅读如何做到这一点,如果这是最好的解决方案。第二个是事务: $db->beginTransaction(); ... $db->commit();
现在“假设”我使用的是事务存储引擎,例如 InnoDB,事务似乎是更常见的解决方案。但是,这是否避免了以下情况:
用户A在网页上->提交数据->开始事务->读取行->计算新值->更新行->保存->提交
用户 B 同时在同一个网页上并同时提交数据,现在可以说它几乎是同时的(用户 B 在开始事务和提交用户 A 的事务之间调用更新函数)用户 B 依赖于用户 A 的事务提交的数据,才能实现准确的计算更新记录。
IE:
数据库行中的开始值:5 用户 A 提交值 5。(开始 事务 -> 读取值 (5) -> 添加提交的值 (5+5=10) -> 写入 更新后的值 -> 保存 -> 提交)
用户 B 提交的值为 7。我需要确保 用户 B 的事务读取为 10,而不是 5(如果未完成更新 阅读前)。
我知道这是一个冗长的解释,我很抱歉,我不确定用于简化问题的正确术语。
谢谢
【问题讨论】:
-
你能做一些像
UPDATE table SET value=value+5这样的事情吗?那么就不需要交易了。 -
这行得通,肯定会让我的生活变得轻松。只有一个我可能会遇到的问题。我进行更新,然后第二个会话在我读取值之前进行更新,我需要将正确的值发送回原始用户。所以这将是一个更新,然后是一个选择来检索当前的“值”。讨厌在读取发生之前进行第二次更新,那么返回的结果将是无效的(或者我不正确)。我担心的原因是数据在更新并返回给用户时必须 100% 保证正确。
-
我不认为你能 100% 正确。即使您确保读取了正确的值,在您将其发送给用户并释放锁定的那一刻,它也可能已过时。除非您有一个接收实时数据库更新的事件驱动系统,否则无法保证您拥有当前值。 (即使那样,也可能会有明显的延迟。)
-
我想得越多,为了准确起见,也许更好的解决方案是审计风格,在其中插入带有设置值的记录,然后使用前一条记录读取该记录,然后前一条记录与插入记录之和返回给用户。我意识到“当前”值可能会更新,但这很好,只要保证计算的值是正确的,并且所有添加的审计历史记录也可以作为有用的副作用提供。
-
那行得通。在这种情况下,您可能需要使用事务。
标签: mysql zend-framework transactions rowlocking