gpt4 book ai didi

php - GET_LOCK 在不应该通过 PHP MySQL/MySQLi 建立两个(应该是)独立连接时成功

转载 作者:行者123 更新时间:2023-11-29 02:25:27 26 4
gpt4 key购买 nike

场景很简单。我们有一个 PHP 脚本:

  • 执行 MySQL 查询 GET_LOCK('TEST', 0)
  • 睡了 5 秒
  • 执行 MySQL 查询 RELEASE_LOCK('TEST')

打开网络浏览器并在 2 个单独的选项卡中调用上述脚本,但调用之间有 1-2 秒的延迟。

  • 预期结果:第一次调用获取“TEST”锁,第二次调用获取“TEST”锁失败。
  • 实际结果:第一次和第二次调用都获得了TEST'锁。

持久连接在 PHP.INI 中被禁用,并且没有使用特定的连接选项来启用它们。 MySQL 和 MySQLi 扩展都产生相同的结果。在两个设置上测试:PHP 5.3.9 + MySQL 5.5.20; PHP 5.4.4 + MySQL 5.5.35。

奇怪的是,通过终端、工作台甚至不同的浏览器执行相同的场景实际上可以按预期工作。我只能通过在同一浏览器中调用脚本来重现该问题(无论具体是哪个浏览器,Opera、Firefox、Chrome 等)。

我找到了 Bug #62002在 MySQL 网站上描述了完全相同的问题,但从未解决或解释过。错误报告中建议执行 SELECT @@pseudo_thread_id,在我的例子中,它有时产生相同的数字,有时产生不同的数字。

我怀疑这两个调用出于某种奇怪的原因是在同一个物理连接上执行的,这可以解释为什么脚本可以获得相同的锁。他们会使用相同的 MySQL session ,并且在这种情况下调用 GET_LOCK 两次会成功。

知道为什么会发生这种情况或如何预防吗?

最佳答案

我想我已经弄清楚了....

信不信由你,这种奇怪的行为是由网络浏览器引起的,更令人震惊的是 - 所有经过测试的浏览器(Opera、Chrome、Firefox)。事实证明,浏览器会对加载具有相同 URL 的页面进行某种特殊处理。

场景:假设我们正在两个单独的选项卡中加载脚本 http://localhost/test.php,彼此之间间隔 2 秒。想象一个简单的脚本,输出当前时间,休眠 10 秒,然后再次输出当前时间。

预期结果:每个选项卡都异步向服务器发出请求,第二个选项卡的执行时间比第一个选项卡晚 2 秒。每个选项卡都需要 10 秒才能完成执行,第二个选项卡相对于第一个选项卡会晚 2 秒完成。选项卡将显示不同的输出(打印时间将偏移 2 秒)。

实际结果 A (Opera v12):仅向服务器发出了 1 次请求(通过服务器访问日志验证)。第一个选项卡需要 10 秒才能完成执行,第二个选项卡也立即 完成(不是 2 秒后)。选项卡显示相同的输出(打印时间相同)。

实际结果 B(Firefox、Chrome、Opera v20):每个选项卡都按预期向服务器发出请求,但这些请求是同步的。第一个选项卡需要 10 秒才能完成执行,第二个选项卡需要额外的 10 秒,在第一个选项卡后 10 秒完成。选项卡将显示不同的输出(打印时间将偏移 10 秒)。

解决方法:对 URL 进行简单的人为更改即可解决问题。例如,执行http://localhost/test.php 在一个选项卡中,http://localhost/test.php?(已添加问号)在另一个选项卡中。

观察:在脚本中设置各种缓存 header 不会影响结果。使用默认浏览器配置,无需调整。后续测试松了一口气,Internet Explorer v10 产生了预期的结果(令人惊讶),使其成为唯一真正按预期工作的浏览器,谁会想到!

根据这一发现,现在可以理解为什么 MySQL/PHP 中的 GET_LOCK 似乎 行为不当,这实际上是由 web 完全意外的行为引起的浏览器。

关于php - GET_LOCK 在不应该通过 PHP MySQL/MySQLi 建立两个(应该是)独立连接时成功,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22965833/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com