【MYSQL】GET_LOCK使用方法简单解析

背景描述: 在同一进程中,如果开了多个线程操作同一数据,为保证数据准确性,我们可以使用lock来保证互斥,但是如果是多个进程操作同一数据,lock就不行了,此时我们可以使用 基于MYSQL实现的分布式锁来实现。

sql 复制代码
SELECT GET_LOCK(@lockName, @timeout); //lockName==锁,timeout==等待时间,如果超时,不再等待

简单来说 ,就是多个进程去修改数据库的某一个数据(操作同一数据库),此时数据库为了保证准确性,会加一个锁,确保一次只能一个进程的一个线程去访问,其他访问的需要等待,直到持有这个锁。
GET_LOCK实现逻辑(简化版):

(1)MySQL 5.7 以及更早版本中一个连接(代码中构建和数据库的连接)只能持有一个命名锁,如果再次GET_LOCK('xxx', ...),会 自动释放之前的锁,再尝试获取新的锁。之后版本可以管理多个锁。

(2)当在代码中调用SELECT GET_LOCK(@lockName, @timeout); 时,mysql首先会查询当前全局锁表(hash结构)里是否有这个lockname

(3)如果没有,立即插入并记录当前连接信息,返回1。

(4)如果有,当前连接进入等待队列(内部用条件变量 COND_WAIT 实现)。

(5)如果在 timeout 秒内锁被释放 → 插入自己,返回 1。

(6)如果超时还没等到 → 返回 0(注意:此时锁依然在别人手上,不会自动释放)。

(7)异常情况:如果连接断开/SQL 出错 → 返回 NULL;如果等待过程中当前 session 被 kill → 直接中断,返回 NULL。
mysql查看数据库版本:

sql 复制代码
SHOW VARIABLES LIKE 'version';

代码示例:

csharp 复制代码
using System;
using MySql.Data.MySqlClient;
using System.Threading;

class Program
{
    static void Main()
    {
        string connStr = "Server=localhost;Database=test;User ID=root;Password=123456;";

        using (var conn = new MySqlConnection(connStr))
        {
            conn.Open();

            string lockName = "MyApp_DistributedLock";

            // 1. 尝试获取锁(等待超时 10 秒)
            using (var cmd = new MySqlCommand("SELECT GET_LOCK(@lockName, @timeout);", conn))
            {
                cmd.Parameters.AddWithValue("@lockName", lockName);
                cmd.Parameters.AddWithValue("@timeout", 10);

                var result = Convert.ToInt32(cmd.ExecuteScalar());
                if (result == 1)
                {
                    Console.WriteLine("✅ 获取到锁,可以安全执行任务");

                    try
                    {
                        // 模拟需要保护的临界区操作
                        Thread.Sleep(5000);
                    }
                    finally
                    {
                        // 2. 释放锁
                        using (var releaseCmd = new MySqlCommand("SELECT RELEASE_LOCK(@lockName);", conn))
                        {
                            releaseCmd.Parameters.AddWithValue("@lockName", lockName);
                            var releaseResult = Convert.ToInt32(releaseCmd.ExecuteScalar());
                            Console.WriteLine(releaseResult == 1 ? "🔓 锁已释放" : "⚠️ 锁释放失败");
                        }
                    }
                }
                else
                {
                    Console.WriteLine("❌ 未能获取到锁(可能被其他进程占用)");
                }
            }
        }
    }
}
相关推荐
2601_9495936513 小时前
深入解析CANN-acl应用层接口:构建高效的AI应用开发框架
数据库·人工智能
javachen__13 小时前
mysql新老项目版本选择
数据库·mysql
Dxy123931021613 小时前
MySQL如何高效查询表数据量:从基础到进阶的优化指南
数据库·mysql
Dying.Light13 小时前
MySQL相关问题
数据库·mysql
蜡笔小炘14 小时前
LVS -- 利用防火墙标签(FireWall Mark)解决轮询错误
服务器·数据库·lvs
韩立学长14 小时前
基于Springboot泉州旅游攻略平台d5h5zz02(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·spring boot·旅游
Re.不晚15 小时前
MySQL进阶之战——索引、事务与锁、高可用架构的三重奏
数据库·mysql·架构
老邓计算机毕设15 小时前
SSM智慧社区信息化服务平台4v5hv(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·ssm 框架·智慧社区、·信息化平台
麦聪聊数据15 小时前
为何通用堡垒机无法在数据库运维中实现精准风控?
数据库·sql·安全·低代码·架构
2301_7903009615 小时前
Python数据库操作:SQLAlchemy ORM指南
jvm·数据库·python