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;
我希望它等到我提交或回滚第一个事务但它没有,它只是立即将行恢复,就像没有发生行锁定一样。
我做了另一个测试,我更新了第一个cli中的status
字段,在我提交事务之前,我无法看到第二个cli中的更改,证明事务实际上正在运行。
我是误解FOR UPDATE
还是做错了什么?
更新
第二次FOR UPDATE
查询
SELECT
答案 0 :(得分:1)
您看到的行动有效。使用" MVCC",不同的连接可以在行上看到不同的版本。
第一个连接抓取了一种阻止写入的锁,但读取。如果第二个连接已完成FOR UPDATE
或INSERT
或其他"则写入"操作类型,它会被延迟等待释放锁定,或者死锁。 (死锁也需要其他锁定。)
普通模式
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
(无需更新)并获得一些价值。可以将这些线程视为在事务之前或之后获取值,具体取决于所有线程的确切时间。重要的是这些'其他'线程将看到数据的一致视图 - 已应用该事务中的更新 none ,或者已应用 all 。这就是" Atomic"装置