简体   繁体   English

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

[英]MySQL transactions: multiple concurrent transactions and data integrity

I'm using transactions for managing data across several MySQL InnoDB tables in a reasonably complex web application. 我在一个相当复杂的Web应用程序中使用事务来管理几个MySQL InnoDB表中的数据。 Briefly, a given transaction works as follows: 简而言之,给定的交易如下:

  1. Data is read from a row in a "user_point_totals" table 从“user_point_totals”表中的行读取数据
  2. Various machinations calculate what the user's new point total should be 各种阴谋计算用户的新点总数应该是多少
  3. A new entry is created in the "user_point_totals" table reflecting the updated total 在“user_point_totals”表中创建一个新条目,反映更新的总数

Let's say that user A performs some action that has point-related ramifications, step 1 is executed, that thread of execution reads the user's point total into memory, and the application begins calculating the new total. 假设用户A执行一些具有与点相关的分支的动作,执行步骤1,该执行线程将用户的总点数读入内存,并且应用程序开始计算新的总计。 Meanwhile, user B performs an action that has implications for user A's point total, and another transaction begins; 同时,用户B执行对用户A的总分有影响的动作,并开始另一个交易; however, the first transaction has not yet completed, so the second thread gets the same point total value as a starting point as the first transaction (from the same table row). 但是,第一个事务尚未完成,因此第二个线程获得与第一个事务(来自同一个表行)相同的点总值作为起始点。 Subsequently, transaction 1 completes and creates a new user point total with its perception of what the new value should be, and shortly thereafter, transaction 2 completes and creates a new row for the user's point total as well. 随后,事务1完成并创建新的用户点总数,其中感知新值应该是什么,并且此后不久,事务2完成并且还为用户的点总数创建新行。 However, the second transaction's point total is now incorrect, as it fails to account for the new total created by transaction 1. 但是,第二个事务的点总数现在不正确,因为它无法考虑事务1创建的新总数。

My questions are: 我的问题是:

  • Is this scenario impossible due to the atomic nature of transactions, which I apparently don't understand as well as I should? 由于交易的原子性质,这种情况是不可能的,我显然不理解我应该这样做?
  • If not, how does one ensure that data integrity exists in these sorts of situations? 如果没有,如何确保在这些情况下存在数据完整性?

Thanks for your consideration! 谢谢你的考虑!

On the technical level, you could use the table-locking (or row-locking) abilities of MySQL. 在技​​术层面,您可以使用MySQL的表锁定 (或行锁定)功能。 That would allow you to detect if someone is actually computing something using the table. 这将允许您检测是否有人正在使用该表计算某些东西。 On the other hand, this technique would require many considerations like what happens if a process crash, etc. 另一方面,这种技术需要考虑许多因素,例如进程崩溃等情况。

On the practical level, though, I doubt you would want to do something like this. 但是,在实际层面上,我怀疑你是否愿意做这样的事情。 Operators like sum() or avg() in MySQL are already optimised for this need. MySQL中的sum()或avg()等运算符已针对此需求进行了优化。 If what you need to do is a sum over some columns of a table and get the answer in a table, you could use a view or create a temporary table (possible but slower). 如果您需要做的是对表的某些列求和并在表中得到答案,您可以使用视图或创建临时表(可能但更慢)。 You should not have a column that contains a value that could be computed from other columns. 您不应该有一个包含可以从其他列计算的值的列。 This situation leads to incongruities since it is unclear which field is true if the relation doesn't balance. 这种情况导致不协调,因为如果关系不平衡则不清楚哪个字段是真的。 (Is it an input script error or a deliberate re-use of the field by some programmer?) (它是输入脚本错误还是某些程序员故意重用该字段?)

On a second note, be sure to use InnoDB tables on your MySQL instance, otherwise your system won't be fully ACID-compilant, meaning you won't get the atomicity nature you need. 在第二个注释中,确保在MySQL实例上使用InnoDB表,否则您的系统将不会完全ACID编译,这意味着您将无法获得所需的原子性。

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

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