5

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

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

假设用户 A 执行了一些与积分相关的操作,执行第 1 步,执行线程将用户的总积分读入内存,应用程序开始计算新的总积分。同时,用户 B 执行了一个对用户 A 的总积分有影响的动作,另一笔交易开始;但是,第一个事务还没有完成,所以第二个线程获得与第一个事务相同的点总值作为起点(来自同一表行)。随后,事务 1 完成并创建一个新的用户积分总数,它对新值应该是什么的感知,不久之后,事务 2 完成并为用户的积分总数创建一个新行。但是,第二笔交易的总积分现在不正确,

我的问题是:

  • 由于交易的原子性质,这种情况是不可能的,我显然不明白我应该理解的程度吗?
  • 如果不是,如何确保在这些情况下存在数据完整性?

感谢您的考虑!

4

1 回答 1

3

在技​​术层面上,您可以使用 MySQL 的表锁定(或行锁定)能力。这将允许您检测是否有人实际上正在使用该表计算某些东西。另一方面,这种技术需要考虑很多因素,比如如果进程崩溃会发生什么等。

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

第二点,请务必在您的 MySQL 实例上使用 InnoDB 表,否则您的系统将无法完全兼容 ACID,这意味着您将无法获得所需的原子性。

于 2010-09-22T14:15:31.540 回答