-1

我想知道在以下假设情况下会发生什么。假设两位老师给同一个学生上完全相同的课程,他们都想更新学生的成绩,鲍勃的成绩。Bob 目前的平均成绩是 60%,老师 1 想用他得到 70% 的测试来更新他的平均水平,而老师 2 想用他得 40% 的测试来更新他的平均水平。

那么在两位老师同时按下更新按钮的一百万分之一的机会中,精确到瞬间精确到同一时间,会发生什么?它会给出错误消息吗,php 或 mysql 是否会神奇地排队更新,只有第一个分数会更新 bob 的平均值,而第二个用户会出错?

编辑:我担心的是第二个用户必须在第一个用户编辑值后获取值,我正在考虑获取记录然后在 php 中进行计算,然后再次更新记录,但在这种情况下我如何确保第二个用户获取的值是 65% 而不是 60%,这可以通过交易来完成吗?

4

5 回答 5

3

它们不能同时运行动作,总会有微小的差异,因为机器在物理上不可能同时写入相同的信息。可能是微秒或更小的问题,但差异会存在。

通常的解决方案之一是在您的WHERE子句中添加类似的数据,并检查是否已完成更新:

UPDATE students SET `avg` = '70' WHERE id=<some-id> AND `avg` = '60';

然而,像平均值这样的东西通常最好不要以这种方式更新:有一个单独的学生分数表,并自己计算每个学生的这些记录的平均值(如果你愿意,你仍然可以将它“缓存”在学生表中)。

于 2012-06-19T11:28:15.070 回答
2

两者都将通过,最后一个要处理的将是新值。由于数据库系统的一致性保证,您不会得到损坏的数据,但由于这是一个计算值,您可能会得到错误的 数据。

我怀疑这个平均值是根据其他表格中的数据计算得出的值。如果是这种情况,请在一个事务中完成所有工作。将新的测试分数添加到表中,让数据库计算平均值并将结果直接插入到第二个表中。这样,要么保证结果正确,要么 交易失败。这需要一个支持事务的存储引擎(例如,InnoDB)。

于 2012-06-19T11:28:36.630 回答
1

数据库将按顺序更新该行。其中一个查询将首先运行,锁定行(或有时是表 - 取决于查询),下一个查询将排队,直到第一个查询完成。

于 2012-06-19T11:25:10.553 回答
1

如果操作是原子的,您将不会遇到任何麻烦。你的 INSERT 是。两个 INSERT 都将被执行。

不过要小心非原子操作!

这就是交易的地方:http: //dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_transaction

于 2012-06-19T11:26:10.220 回答
1

悲观锁定和事务只是这里故事的一半。数据库将取出行锁,但这只能确保尝试修改同一行的任何人都必须等到当前事务完成。我想防止的情况是:

  1. 教师 a 查看作业但看不到成绩。
  2. 教师 b 查看作业并没有看到成绩。
  3. 老师a给70分。
  4. b老师给40分。

b 很可能并不是要覆盖 a。最好的保护是某种形式的乐观锁定。当两个人同时进行编辑时,您会在 wiki 中看到这一点。较晚的提交者必须确认编辑,因为它可能会意外地反转较早的提交者的更改。在评分情况下,您可以在 where 子句中添加显示给用户的旧成绩,然后断言更新更改了一行。

UPDATE GRADES SET SCORE=70 WHERE NAME='Jim' AND SCORE=0;
于 2012-06-19T11:44:15.627 回答