我有一个secenario,我必须在MYSQL中执行update insert(我必须使用REPEATABLE-READ隔离级别)
塞克纳里奥是-

there is a table -
+----+--------+--------+--------+
| ID |  NAME  | AMOUNT | STATUS |
+----+--------+--------+--------+
|  1 |  NAME1 |  700   | ACTIVE |
+----+--------+--------+--------+

现在,NAME=NAME1的每个新条目都应该用STATUS=INACTIVE更新旧条目,然后插入新条目,即。
+----+--------+--------+----------+
| ID |  NAME  | AMOUNT |  STATUS  |
+----+--------+--------+----------+
|  1 |  NAME1 |  700   | INACTIVE |
+----+--------+--------+----------+
|  2 |  NAME1 |  800   |  ACTIVE  |
+----+--------+--------+----------+

如果有两个事务要插入新分录(一个事务的金额为800,另一个事务的金额为900),则应将旧分录标记为不活动,然后插入新分录。所以表的最终输出(第一个实例)应该是
+----+--------+--------+----------+
| ID |  NAME  | AMOUNT |  STATUS  |
+----+--------+--------+----------+
|  1 |  NAME1 |  700   | INACTIVE |
+----+--------+--------+----------+
|  2 |  NAME1 |  800   | INACTIVE |
+----+--------+--------+----------+
|  3 |  NAME1 |  900   |  ACTIVE  |
+----+--------+--------+----------+

显然,会有竞争条件,但是没有问题,结果表应该只有一个活动记录NAME=NAME1
现在的问题是-两个事务都是通过更新已经插入的行来插入记录的。最后我得到了两张活动唱片。即。
+----+--------+--------+----------+
| ID |  NAME  | AMOUNT |  STATUS  |
+----+--------+--------+----------+
|  1 |  NAME1 |  700   | INACTIVE |
+----+--------+--------+----------+
|  2 |  NAME1 |  800   |  ACTIVE  |
+----+--------+--------+----------+
|  3 |  NAME1 |  900   |  ACTIVE  |
+----+--------+--------+----------+

+--------------------------+-------------------------------+
|   T1                     |             T2                |
+--------------------------+-------------------------------+
|  START                   |    START                      |
|  update entry(ID=1)      | wait for lock on entry(ID=1)  |
|  insert new entry(ID=2)  |                               |
|  commit                  |                               |
|                          | update entry(ID=1)            |
|                          | insert new entry(ID=3)        |
|                          | commit                        |
+--------------------------+-------------------------------+

我正在使用(而且必须使用)可重复读取,因此在这种情况下,T2应该(在T1之前)得到新的插入行(我认为这是幻影读取的情况),但它没有发生。
任何关于如何最好地实现这一点的建议也会有帮助。
谢谢

最佳答案

使用隔离级别SERIALIZABLE就不用担心了。不,您不必使用REPEATABLE READ。您还可以设置每个会话的隔离级别。没有其他理由不这么做。

10-08 13:40
查看更多