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

jus*_*ach 6 mysql database transactions data-integrity

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

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

假设用户 A 执行了一些与积分相关的操作,执行步骤 1,执行线程将用户的积分总数读入内存,并且应用程序开始计算新的总数。同时,用户 B 执行的操作会影响用户 A 的总积分,并且另一笔交易开始;但是,第一个事务尚未完成,因此第二个线程获取与第一个事务相同的点总值作为起点(来自同一表行)。随后,事务 1 完成并创建一个新的用户总积分,并了解新值应该是什么,此后不久,事务 2 完成并为用户总积分创建一个新行。但是,第二笔交易的积分总数现在不正确,因为它无法说明交易 1 创建的新总分。

我的问题是:

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

感谢您的考虑!

Sor*_*vux 3

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

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

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