使用PHP锁定MySQL表

7

脚本1。

$query_ = "lock tables test1 as test11 write";
mysql_query($query);
$query_ = "select * from test11";
sleep(20);
$query_ = "unlock tables";
mysql_query($query_);

脚本 2。

$query_ = "select * from test1";
$result = mysql_query($query_);

问题在于当我运行第一个脚本时,如果同时运行第二个脚本,则表未被锁定。我可以从中读取任何数据。

我需要它被锁定并返回错误。

如何使其正常工作?


这可能不能回答你的问题,但你应该停止使用 mysql_* 函数。它们已被弃用。相反,使用 PDO(自 PHP 5.1 起支持)或 mysqli(自 PHP 4.1 起支持)。如果不确定使用哪个,请阅读本文 - Matt
我相信表格只会被锁定在特定的mysql连接实例中。我认为它的工作原理是为了防止竞态条件的发生。 - Travesty3
为什么要针对特定的mysql连接进行锁定?当我不插入任何内容时,我的脚本为什么还想要插入东西呢? - pain.reign
也许我对此有误解。可能我感到困惑,而我所考虑的是它在脚本执行期间自动锁定表以防止竞争条件...抱歉,我在这方面没有提供太多帮助。 - Travesty3
4个回答

9
如果您不希望其他人访问该表,则使用 标签。
LOCK TABLES test1 WRITE;

其他脚本不会返回错误,但会等待锁被释放。

希望这有所帮助...


我尝试过了,仍然无法锁定任何内容。第二个脚本可以轻松访问数据。 - pain.reign
2
从你的第一个脚本看来,首先你在test1上放置了写锁,然后执行查询,睡眠20秒,然后解锁表。在你解锁之前,第二个脚本一直在等待表解锁。一旦表解锁,第二个脚本中的查询就可以访问该表并返回数据。尝试将睡眠时间增加到100或200,然后检查结果。 - jsist

6
您正在使用$query_ = "lock tables test1 as test11 read";对表进行read锁定,这意味着其他查询仍然可以无任何问题地读取它(相关链接请参考此处- 滚动到锁类型的部分): read锁类型的信息:
  • 持有锁的会话可以读取该表(但无法写入)。
  • 多个会话可以同时为该表获取READ锁。
  • 其他会话可以在不明确获取READ锁的情况下读取该表。
如果您想要阻止任何其它任务读取表,请使用以下方式的write锁。
$query_ = "lock tables test1 as test11 write";

1
我将修饰符更改为“写”,但第二个脚本仍返回所有记录。 - pain.reign
@pain.reign,表上的锁是会话特定的,这是一个随意的问题(很酷),还是您正在尝试模拟对您正在锁定的表的事务? - Fluffeh
如果你想使用事务处理 mysql_* 函数,我相信语法是 mysql_query("BEGIN");(你可能还需要一个 autocommit=0),以 mysql_query("commit"); 结束- 话虽如此,如果你转移到 PDO,你可以很容易地使用 beginTransaction 进行事务处理。 - Fluffeh
尝试过使用mysql_query("BEGIN")和设置autocommit = 0,但仍然无法锁定。 - pain.reign
2
@still_dreaming_1 读锁定将防止任何会话在锁定期间写入表格 - 尽管其他会话也可能同时获取读锁定。会话从执行应用程序建立连接到连接终止的时间保持不变(无论是在代码中还是在代码执行完成时)。 - Fluffeh
显示剩余5条评论

2

您需要授予数据库用户锁定表的权限。


1
你对锁的作用有一个误解。锁不会阻止其他脚本访问数据,相反,锁影响其他脚本访问数据的时间。当脚本2尝试访问或修改由于锁而不允许的数据时,它将暂停并等待锁被释放。在脚本1解锁表格后,脚本2将继续进行并完成而没有任何问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接