5

我有两个 php 页面,page1.php & page2.php

page1.php

execute_query('START TRANSACTION');
$res =execute_query('SELECT * FROM table WHERE id = 1 FOR UPDATE');

sleep(20);

print $res->first_name;
execute_query('COMMIT');

print"\n OK";

page2.php

 $res =execute_query('SELECT * FROM table WHERE id = 1');
print $res->first_name;

我几乎同时执行两个页面

所以根据mysql的'FOR UPDATE'条件,page2.php中的结果只有在page1.php执行后才会显示(即page1.php中显示'OK'后),因为两个页面都读取同一行。

但正在发生的事情是,

page2.php 突然显示结果,甚至在 page1.php 执行完成之前

我可以知道'FOR UPDATE'命令有什么问题吗?

4

2 回答 2

2

我假设该表是InnoDB(不是MyISAMMEMORY)。您SELECT在事务中使用 a。我不知道你的隔离级别,但我猜你的事务没有互相阻塞。

有关详细信息,请参阅此页面:http: //dev.mysql.com/doc/refman/5.5/en/set-transaction.html

编辑:

根据要求,我将更好地解释这个概念。隔离级别是一个会话/全局变量,它决定了事务的执行方式。某些隔离级别在尝试修改同一行时会阻止其他事务,但某些隔离级别不会。

例如,如果您使用UNCOMMITTED,它不会阻止任何内容,因为您访问的是行的实际版本(在事务结束之前可能会过时)。另一个SELECT(page2)只读取表,因此不必等待第一个事务结束。

SERIALIZABLE安全得多。它不是默认值,因为它是最慢的隔离级别。如果您正在使用它,请确保它FOR UPDATE仍然对您有意义。

于 2013-04-29T08:14:48.903 回答
-1

I Think your SELECT FOR UPDATE is inside BEGIN TRANSACTION, so it will not lock the record until COMMIT statement reached , and you delayed execution with sleep(20). so page2.php will be execute.

于 2013-04-29T08:30:46.527 回答