MySQL事务:多个并发事务和数据完整性

时间:2010-09-22 13:56:31

标签: mysql database transactions data-integrity

我正在使用事务来管理一个相当复杂的Web应用程序中的几个MySQL InnoDB表中的数据。简而言之,给定的交易如下:

  1. 从“user_point_totals”表中的行读取数据
  2. 各种阴谋计算用户的新点总数应该是多少
  3. 在“user_point_totals”表中创建一个新条目,反映更新的总数

假设用户A执行一些具有与点相关的分支的操作​​,执行步骤1,该执行线程将用户的点总数读入内存,并且应用程序开始计算新的总数。同时,用户B执行对用户A的总分有影响的动作,并开始另一个交易;但是,第一个事务尚未完成,因此第二个线程获得与第一个事务(来自同一个表行)相同的点总值作为起始点。随后,事务1完成并创建新的用户点总数,其中感知新值应该是什么,并且此后不久,事务2完成并且还为用户的点总数创建新行。但是,第二个交易的点总数现在不正确,因为它无法考虑交易1创建的新总额。

我的问题是:

  • 由于交易的原子性质,这种情况是不可能的,我显然不理解这一点吗?
  • 如果没有,如何确保在这些情况下存在数据完整性?

感谢您的考虑!

1 个答案:

答案 0 :(得分:3)

在技术层面,您可以使用MySQL的table-locking(或行锁定)功能。这将允许您检测是否有人正在使用该表计算某些东西。另一方面,这种技术需要考虑许多因素,例如在进程崩溃等情况下会发生什么。

但在实际层面上,我怀疑你是否愿意做这样的事情。 MySQL中的sum()或avg()等运算符已针对此需求进行了优化。如果您需要做的是对表的某些列求和并在表中得到答案,您可以使用视图或创建临时表(可能但更慢)。您不应该有一个包含可以从其他列计算的值的列。这种情况导致不协调,因为如果关系不平衡则不清楚哪个字段是真的。 (这是一个输入脚本错误还是某个程序员故意重用该字段?)

在第二个注释中,请确保在MySQL实例上使用InnoDB表,否则您的系统将不会完全ACID编译,这意味着您将无法获得所需的原子性。