FOR UPDATE似乎没有锁定MySql InnoDB中的行

FOR UPDATE似乎没有锁定MySql InnoDB中的行,mysql,transactions,locking,innodb,rowlocking,Mysql,Transactions,Locking,Innodb,Rowlocking,MySql=v5.6 表引擎=InnoDB 我打开了一个mysql cli。我运行: 启动交易 从my_表中选择id,其中id=1用于更新 然后,我打开并运行第二个cli: 从my_表中选择id,其中id=1 我希望它等待我提交或回滚第一个事务,但它没有,它只是直接返回行,就好像没有发生行锁定一样 我做了另一个测试,在第一个cli中更新了一个状态字段,在提交事务之前,我无法在第二个cli中看到该更改,这证明了事务确实在工作 我是对更新有误解还是做错了什么 更新: 需要在第二次选择查询时更新,您看

MySql=v5.6

表引擎=InnoDB

我打开了一个mysql cli。我运行:

启动交易

从my_表中选择id,其中id=1用于更新

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

从my_表中选择id,其中id=1

我希望它等待我提交或回滚第一个事务,但它没有,它只是直接返回行,就好像没有发生行锁定一样

我做了另一个测试,在第一个cli中更新了一个状态字段,在提交事务之前,我无法在第二个cli中看到该更改,这证明了事务确实在工作

我是对更新有误解还是做错了什么

更新:


需要在第二次选择查询时更新,您看到的操作有效。使用MVCC,不同的连接可以在行上看到不同的版本

第一个连接捕获了一种类型的锁,它阻止写入,但不阻止读取。如果第二个连接完成了更新、插入或其他写入类型的操作,那么它可能会延迟等待释放锁,或者死锁。死锁还需要其他锁

共同模式

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


同时,其他线程可以选择不进行更新并获得一些值。将这些线程视为在事务之前或之后获取值,具体取决于所有线程的精确计时。重要的是,这些“其他”线程将看到数据的一致视图——要么该事务中的任何更新都未应用,要么所有更新都已应用。这就是原子的含义。

当表被锁定并且选择被读取时,可以读取function@Rafiq很抱歉,我不明白你的意思?你可以看到这个文档@Rafiq-表锁定似乎与这个问题无关。行锁定是相关的。谢谢Rick。有读锁这样的东西吗?基本上,表包含排队的项目,我有多个线程处理它们-我不希望一个项目被处理两次。有MySql模式吗?for UPDATE允许读取,但阻止写入。我马上补充我的答案。谢谢!我缺少的关键点是第二个SELECT查询也必须用于更新。这项工作现在和预期的一样。但它们确实需要包含在事务中吗?还是有别的办法?
BEGIN;
SELECT ... FOR UPDATE; -- the row(s) you will update in this transaction
miscellany work
UPDATE...;  -- those row(s).
COMMIT;