MySQL在高负载、竞争条件下?
在我参与的一个应用程序中,我遇到的似乎是竞争条件的影响。情况如下,通常,负责一些重应用程序逻辑的页面采用以下格式: 从MySQL在高负载、竞争条件下?,mysql,Mysql,在我参与的一个应用程序中,我遇到的似乎是竞争条件的影响。情况如下,通常,负责一些重应用程序逻辑的页面采用以下格式: 从test中选择,并确定是否已经有行与子句匹配。 如果匹配行已经存在,我们在这里终止,否则继续应用程序逻辑 在test表中插入与初始选择匹配的值 通常情况下,这可以很好地工作,并将操作限制为一次执行。然而,在高负载和用户滥用的情况下,许多请求被故意同时发送,MySQL允许许多应用程序逻辑实例运行,从而绕过select子句的限制 它实际上似乎运行着类似于: 从测试中选择 从测试中选择
test
中选择,并确定是否已经有行与子句匹配。如果匹配行已经存在,我们在这里终止,否则继续应用程序逻辑
在
test
表中插入与初始选择匹配的值
通常情况下,这可以很好地工作,并将操作限制为一次执行。然而,在高负载和用户滥用的情况下,许多请求被故意同时发送,MySQL允许许多应用程序逻辑实例运行,从而绕过select子句的限制
它实际上似乎运行着类似于:从测试中选择
从测试中选择
从测试中选择
(全部通过检查)
插入测试
插入测试
插入测试 我相信这样做是为了提高效率,但在我的应用程序中,它会产生严重的影响。我尝试使用Get_Lock()和Release_Lock(),但这在高负载下似乎不够,因为竞争条件似乎仍然存在。事务也是不可能的,因为应用程序逻辑非常繁重,并且涉及的所有表都不支持事务
对于熟悉这种行为的人来说,是否可以关闭这种类型的处理,以便MySQL始终按照接收查询的顺序处理查询?有没有其他方法使这种查询原子化?对此问题的任何帮助都将不胜感激,我找不到关于这种行为的详细记录。就我个人而言,我会以另一种方式进行检查 尝试插入该行。如果它失败了,那么那里已经发生了争吵
通过这种方式,您可以在单个查询中检查或复制并插入新行,从而消除竞争的可能性。这里的问题是,正如您所猜测的,您有一个竞争条件
选择
和插入
必须是一个原子单位
您这样做的方式是通过事务。您无法安全地进行选择
,返回PHP,并假设在进行插入
时,选择
的结果将反映数据库状态
如果如您所说,设计良好的事务(正确的解决方案)是不可能的——我仍然强烈推荐它们——那么您将不得不以原子方式进行最后的插入,检查其假设是否仍然正确(例如通过插入(如果不存在)
、存储过程,或捕获应用程序中的插入
错误)。如果不存在,它将中止返回到PHP代码,而PHP代码必须重新启动逻辑
顺便说一句,MySQL可能是按照接收请求的顺序执行请求的。通过多个同时连接可以接收选择A
,选择B
,插入A
,插入B
。因此,唯一的“解决方案”一次只允许一个连接-这将扼杀您的可伸缩性。谢谢,这似乎是一个可能的解决方案。如何进行原子化检查假设是否仍然正确。如果通过逻辑顶部的简单选择,新数据是否仍不可能反映在选项卡中le?@majicbunnie您将第二个插入存储过程,该存储过程执行开始事务;选择;[检查];INSERT;END TRANSACTION;
。谢谢,我认为这对我来说是可行的,尽管我可能需要更改某些存储引擎类型以支持事务。据我所知,它们都必须具有事务功能,这样的解决方案才能正常工作。