首页 > 数据库 >MySQL的for update skip locked

MySQL的for update skip locked

时间:2025-01-06 09:47:27浏览次数:1  
标签:status locked skip update UPDATE 任务 LOCKED 锁定 id

最近有一个功能要是音频转文字以及翻译,该任务不仅耗时还消耗硬件,在硬件能够支持的情况下可以启动多台电脑一起处理任务加快速度,启动多个程序会出现处理同一个任务的问题,也就是并发的问题,趁机了解了一下mysql的FOR UPDATE SKIP LOCKED

MySQL 中,FOR UPDATE SKIP LOCKED 是一个强大的功能,通常用于解决并发环境中的任务分配问题,确保每个任务只被一个进程处理。它允许查询未被锁定的记录,并跳过那些已经被其他事务锁定的记录。

FOR UPDATE SKIP LOCKED 解释

  • FOR UPDATE:锁定查询到的行,防止其他事务对这些行进行修改。
  • SKIP LOCKED:跳过那些已经被其他事务锁定的行,返回未被锁定的记录。

这种方法非常适用于任务队列场景,可以避免任务被多个进程同时处理。

MySQL 8.0+ 示例

假设我们有一个任务表 tasks,其中包含任务的状态。

任务表结构

CREATE TABLE tasks (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255),
    status INT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

状态含义

  • status = 1:任务待处理
  • status = 2:任务正在处理中
  • status = 3:任务已完成

查询并锁定未处理的任务

我们可以使用 FOR UPDATE SKIP LOCKED 查询并锁定待处理的任务。此查询会锁定一行记录,如果该记录已被其他事务锁定,则跳过该记录,返回未被锁定的记录。

查询并锁定任务

START TRANSACTION;

SELECT id, name
FROM tasks
WHERE status = 1
FOR UPDATE SKIP LOCKED
LIMIT 1;

这个查询将:

  • 锁定一个 status = 1(待处理)的任务。
  • 如果该任务已经被其他事务锁定,它将跳过这行记录,返回一个未被锁定的任务。
  • 通过 LIMIT 1 限制每次查询一个任务。

更新任务状态

UPDATE tasks
SET status = 2, updated_at = NOW()
WHERE id = <TASK_ID>;

COMMIT;

执行完任务后,更新任务的 status 字段为 2,表示任务正在处理中,最后提交事务。


Python 使用示例

如果你使用 PythonSQLAlchemy 来处理任务,可以像下面这样实现:

from sqlalchemy import create_engine, text
from sqlalchemy.orm import sessionmaker

# 数据库连接
engine = create_engine("mysql+pymysql://user:password@localhost/database")
Session = sessionmaker(bind=engine)

def fetch_and_process_task():
    with Session() as session:
        # 查询并锁定任务
        task = session.execute(
            text("""
                SELECT id, name
                FROM tasks
                WHERE status = 1
                FOR UPDATE SKIP LOCKED
                LIMIT 1
            """)
        ).fetchone()

        if task:
            task_id = task.id
            # 更新任务状态
            session.execute(
                text("""
                    UPDATE tasks
                    SET status = 2, updated_at = NOW()
                    WHERE id = :task_id
                """),
                {"task_id": task_id}
            )
            session.commit()

            # 模拟任务处理
            print(f"Processing task: {task.name}")
        else:
            print("No pending tasks available.")

注意事项

  1. 版本要求FOR UPDATE SKIP LOCKED 是 MySQL 8.0 及以上版本的功能,旧版本的 MySQL 不支持此功能。
  2. 锁定行:使用 FOR UPDATE 锁定的行会阻止其他事务修改该行,直到事务提交。
  3. 跳过锁定SKIP LOCKED 允许跳过已被其他事务锁定的行,确保并发的任务处理不会发生冲突。
  4. 事务管理:确保在事务内执行 SELECTUPDATE,以保持一致性。

总结

  • FOR UPDATE SKIP LOCKED 是 MySQL 中用于并发任务处理的有力工具,可以避免任务重复执行。
  • 适用于分布式任务队列和需要高并发的场景,确保任务不会被多个进程同时处理。

标签:status,locked,skip,update,UPDATE,任务,LOCKED,锁定,id
From: https://www.cnblogs.com/dx5800/p/18590788

相关文章

  • InnerAudioContext.offTimeUpdate
    InnerAudioContext.offTimeUpdate(functionlistener)基础库1.9.0开始支持,低版本需做兼容处理。小程序插件:支持功能描述移除音频播放进度更新事件的监听函数参数functionlisteneronTimeUpdate传入的监听函数。不传此参数则移除所有监听函数。示例代码constliste......
  • SQL 基础教程 - SQL UPDATE 语句
    SQL UPDATE 语句UPDATE语句用于更新表中的记录。SQLUPDATE语句UPDATE语句用于更新表中已存在的记录。SQLUPDATE语法UPDATEtable_nameSETcolumn1=value1,column2=value2,...WHEREcondition;参数说明:table_name:要修改的表名称。column1,column2,........
  • MySQL索引优化-Count优化、limit优化、Update优化
    一、limit优化这里我有一张表tb_sku里面有400w条数据,以这个表作为案例对象在数据量比较大时,如果进行 limit 分页查询,在查询时,越往后,分页查询效率越低。我们一起来看看执行 limit 分页查询耗时对比:1. 未优化案例(1)查询起始索引0后面10条记录select*fromtb_skuli......
  • Updated ChangeIP DDNS script for ROS 7.xx
    填写账号密码,域名即可,如果是非pppoe-out1,请自行修改接口 :globalddnsuser"xxxx":globalddnspass"xxxx":globalddnshost"xxxx.25u.com":globalddnsip:globalddnsipfn:globalddnslastip[:tostr[:resolve$ddnshost]]:if([:typeof$ddnslast......
  • DownloadTask.onProgressUpdate
    DownloadTask.onProgressUpdate(functionlistener)基础库1.4.0开始支持,低版本需做兼容处理。小程序插件:支持相关文档:网络使用说明、局域网通信功能描述监听下载进度变化事件参数functionlistener下载进度变化事件的监听函数参数Objectres属性类型说......
  • UploadTask.offProgressUpdate
    UploadTask.offProgressUpdate(functionlistener)基础库2.1.0开始支持,低版本需做兼容处理。小程序插件:支持相关文档:网络使用说明、局域网通信功能描述移除上传进度变化事件的监听函数参数functionlisteneronProgressUpdate传入的监听函数。不传此参数则移除......
  • UploadTask.onProgressUpdate
    UploadTask.onProgressUpdate(functionlistener)基础库1.4.0开始支持,低版本需做兼容处理。小程序插件:支持相关文档:网络使用说明、局域网通信功能描述监听上传进度变化事件参数functionlistener上传进度变化事件的监听函数参数Objectres属性类型说明......
  • [Windows] 启动 Windows Update 服务失败,报:"Windows 无法启动 Windows Update 服务(
    1问题描述现象1:Windows10家庭版-服务(services.msc)-启动WindowsUpdate服务失败,报:"Windows无法启动WindowsUpdate服务(位于本地计算机上)错误126:找不到指定的模块"注:C:\Windows\System32\wuaueng.dll文件存在注:注册表regedit:计算机\HKEY_LOCAL......
  • 记 Redisson 报错 attempt to unlock lock, not locked by current thread
    原文:记一次Redisson线上问题→你怎么能释放别人的锁错误信息:attempttounlocklock,notlockedbycurrentthreadbynodeid:b9df1975-5595-42eb-beae-bdc5d67bce49thread-id:52查看日志,找到对应的堆栈信息:Exceptioninthread"thread0"java.lang.IllegalMoni......
  • PreDownloadSubpackageTask.onProgressUpdate
    PreDownloadSubpackageTask.onProgressUpdate(functionlistener)基础库2.27.3开始支持,低版本需做兼容处理。小程序插件:不支持功能描述监听分包加载进度变化事件参数functionlistener分包加载进度变化事件的监听函数参数Objectres属性类型说明progres......