1

MySql = v5.6

表引擎 = InnoDB

我打开了一个 mysql cli。我跑:

START TRANSACTION;

SELECT id FROM my_table WHERE id=1 FOR UPDATE;

然后我打开并运行第二个 cli:

SELECT id FROM my_table WHERE id=1;

我希望它等到我提交或回滚第一个事务,但它没有,它只是立即带回行,就好像没有发生行锁定一样。

我做了另一个测试,我status在第一个 cli 中更新了一个字段,但在我提交事务之前我看不到第二个 cli 中的更改,证明事务确实有效。

我是误会FOR UPDATE还是做错了什么?

更新:

FOR UPDATE第二次SELECT查询需要

4

1 回答 1

1

你看到的那个动作是有效的。使用“MVCC”,不同的连接可以在行上看到不同的版本。

第一个连接获取了一种锁定类型,它阻止写入,但不阻止读取。如果第二个连接已经完成FOR UPDATEINSERT其他“写入”类型的操作,它会被延迟等待释放锁,或者死锁。(死锁也需要其他锁。)

常见模式

BEGIN;
SELECT ... FOR UPDATE; -- the row(s) you will update in this transaction
miscellany work
UPDATE...;  -- those row(s).
COMMIT;

如果两个线程在同一行的“同一”时间运行该代码,则第二个线程将停在SELECT..FOR UPDATE. 第一个线程完成后,SELECT将运行,获取新值。一切都很好。

同时,其他线程可以SELECT(无需更新)并获得一些价值。将这些线程视为在事务之前或之后获取值,具体取决于所有线程的确切时间。重要的是这些“其他”线程将看到一致的数据视图——要么没有应用该事务中的任何更新,要么已应用所有更新。这就是“原子”的意思。

于 2016-09-26T18:44:32.427 回答