我有两个php页面,page1.php&使page2.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";
$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'命令有什么问题。?
答案 0 :(得分:2)
我假设该表格为InnoDB
(不是MyISAM
或MEMORY
)。
您在交易中使用SELECT
。我不知道你的隔离级别,但我猜你的交易没有相互阻塞。
有关详情,请参阅此页:http://dev.mysql.com/doc/refman/5.5/en/set-transaction.html
修改强>
我将按要求更好地解释这个概念。隔离级别是会话/全局变量,用于确定执行事务的方式。某些隔离级别在尝试修改同一行时阻止其他事务,但某些隔离级别不会。
例如,如果您使用UNCOMMITTED
,则它不会阻止任何内容,因为您访问行的实际版本(在事务结束之前可能会过时)。另一个SELECT
(第2页)只读取表,因此不必等待第一个事务结束。
SERIALIZABLE
更加安全。它不是默认值,因为它是最慢的隔离级别。如果您正在使用它,请确保FOR UPDATE
仍然适合您。
答案 1 :(得分:0)
我认为您的SELECT FOR UPDATE
位于BEGIN TRANSACTION
内,因此在COMMIT
语句到达之前它不会锁定记录,并且您使用sleep(20)
延迟执行。所以page2.php
将被执行。