首页 > 解决方案 > MySQL 分页检索数据,避免竞争条件

问题描述

我的服务是集群的,我正在运行它的几个实例。我需要以分页方式收集所有实体并将它们推送到缓存层(Redis)。在一台应用程序服务器上执行此操作时,在服务器 #2 上运行的应用程序可能已经在进行更改。

那些对 db 的分页调用将在一次调用中获取 1000 个项目。现在,由于我想在检索过程中防止修改,我该如何实现呢?

SELECT FOR UPDATE即使我没有更新此事务中的任何内容,但仅以分页方式获取数据,我是否可以使用机制?

标签: mysqldatabase

解决方案


如果它是一个具有多个线程的应用程序实例,则可以使用临界区。但这不适用于应用程序实例集群。

几个月前,我为一项服务实现了这一点。该应用程序部署在多个实例中。这些实例不相互通信,因此它们不能直接协调。但它们都连接到同一个 MySQL 数据库。

我所做的是使用 MySQL 的GET_LOCK()内置函数。

当例程想要独占访问时,它会调用GET_LOCK('mylock', 0). 这会立即返回,如果它获得了锁,则返回一个值,如果该锁已被其他某个客户端持有,则返回一个假值。这告诉客户端应用程序它是否是“赢家”。

如果客户不是赢家,那么它会打电话GET_LOCK('mylock', -1),这意味着无限期地等待。这样做是因为获胜者正在处理关键部分需要做的任何事情。

当获胜者结束时,它必须跟注RELEASE_LOCK('mylock')。这会解除对等待的客户的阻止。他们现在知道临界区的工作已经完成,他们可以随意读取缓存的内容或他们需要做的任何其他事情。

还要记住,正在等待的客户端GET_LOCK('mylock', -1)需要RELEASE_LOCK('mylock')立即调用,因为一旦他们停止等待,他们实际上是自己获得了锁。

这种设计允许多个客户端使用单个锁协调器 (MySQL)。它实现了悲观锁定,无需依赖锁定任何表或行集。


推荐阅读