如何在MySQL中利用唯一索引的原子性实现高性能的分布式锁?

轻辰君_9492

轻辰君_9492

2026-06-10

904人浏览

原创

唯一索引不能自动实现高性能分布式锁,必须配合过期检查、持有者校验和重试机制,否则易导致空转、误删或死锁。

如何在mysql中利用唯一索引的原子性实现高性能的分布式锁?

不能靠唯一索引“自动”实现高性能分布式锁——它本身不阻塞、不等待,必须配合重试、过期和校验逻辑才能用,否则极易出现空转、误删、死锁。

为什么INSERT + 唯一索引不是开箱即用的锁

很多人以为建好表、写个 INSERT INTO distributed_lock (lock_key, client_id, expire_time) VALUES ('order_1001', 'abc', NOW() + INTERVAL 30 SECOND) 就算加锁成功了。其实这只是原子性判别起点,离“可用锁”还差三步:是否已过期、是否被别人持有、失败后要不要等。MySQL 不会主动阻塞后续请求,INSERT 失败就直接报错(Duplicate entry 'order_1001' for key 'uk_lock_key'),业务层必须自己处理这个错误并决定重试策略。

  • 不带 expire_time 字段 → 服务宕机后锁永远不释放,变成死锁
  • 没存 client_id → 释放时只能 DELETE FROM distributed_lock WHERE lock_key = 'xxx',结果删掉别人刚续期的锁
  • 插入后不校验影响行数 → 把主键冲突、字段超长等非锁冲突误判为“抢锁失败”

建表必须包含这四个字段且满足约束

唯一索引只是基础,真正起作用的是字段组合与语义约定。下面这张表结构是生产可用的最小闭环:

MySQL
MySQL

编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。

下载
CREATE TABLE `distributed_lock` (
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  `lock_key` VARCHAR(64) NOT NULL COMMENT '资源标识,如 order:1001',
  `client_id` VARCHAR(64) NOT NULL COMMENT '本机标识,建议 IP+端口+UUID',
  `expire_time` DATETIME NOT NULL COMMENT '绝对过期时间,非 TTL',
  `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_lock_key` (`lock_key`)
) ENGINE=InnoDB;
  • lock_key 必须是业务维度的最小粒度标识(不能用模糊前缀如 order:),否则无法精确释放
  • client_id 不能用线程 ID 或随机字符串——它要能被服务实例稳定生成、跨重启一致
  • expire_time 必须是 DATETIME 类型的绝对时间(如 NOW() + INTERVAL 30 SECOND),不用 TIMESTAMP 避免时区转换歧义
  • 不要加 ON UPDATE CURRENT_TIMESTAMP 到 expire_time,否则续期操作会干扰判断

获取锁时必须检查三件事,缺一不可

单纯执行 INSERT 只完成一半工作。一次安全的加锁流程应包含:

  • 先尝试 INSERT,若影响行数为 1 → 加锁成功,立刻返回
  • 若报错 Duplicate entry → 立即查表:SELECT client_id, expire_time FROM distributed_lock WHERE lock_key = 'order_1001'
  • 查到记录后,检查 expire_time :成立则说明锁已过期,用 <code>UPDATE ... WHERE lock_key = ? AND expire_time 尝试覆盖(注意:该 <code>UPDATE 必须同时更新 client_id 和 expire_time,否则可能覆盖别人的有效锁)
  • 如果 UPDATE 影响行为 1 → 覆盖成功,相当于“抢过期锁”,可继续;否则说明锁仍有效,当前客户端必须放弃或等待

释放锁必须用条件删除,且不能放在事务里

最常见误操作是:在业务事务中执行 DELETE FROM distributed_lock WHERE lock_key = 'xxx'。一旦事务回滚,锁被删了但业务状态没提交,等于白加;更糟的是,如果事务卡住未提交,锁一直挂着,其他节点全被堵死。

  • 释放操作必须独立于业务事务,走单独连接执行
  • 删除语句必须同时校验 lock_key 和 client_id:DELETE FROM distributed_lock WHERE lock_key = 'order_1001' AND client_id = '10.0.1.5:8080:abc123'
  • 不要依赖 expire_time 做删除条件——它只用于加锁阶段的过期判定,释放时只认身份
  • 执行后检查影响行数:为 0 表示锁已被别人释放或根本不存在,此时不应报错,而是静默忽略

真正难的从来不是“怎么加锁”,而是“怎么确认锁还归我管”——所有绕过 client_id 校验或忽略 expire_time 检查的设计,上线后都会在凌晨三点准时爆发。

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

相关标签:

mysql

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
mysql修改数据表名
mysql修改数据表名

MySQL修改数据表:1、首先查看数据库中所有的表,代码为:‘SHOW TABLES;’;2、修改表名,代码为:‘ALTER TABLE 旧表名 RENAME [TO] 新表名;’。php中文网还提供MySQL的相关下载、相关课程等内容,供大家免费下载使用。

2023.06.20

2273

6

MySQL创建存储过程
MySQL创建存储过程

存储程序可以分为存储过程和函数,MySQL中创建存储过程和函数使用的语句分别为CREATE PROCEDURE和CREATE FUNCTION。使用CALL语句调用存储过程智能用输出变量返回值。函数可以从语句外调用(通过引用函数名),也能返回标量值。存储过程也可以调用其他存储过程。php中文网还提供MySQL创建存储过程的相关下载、相关课程等内容,供大家免费下载使用。

2023.06.21

1399

5

mongodb和mysql的区别
mongodb和mysql的区别

mongodb和mysql的区别:1、数据模型;2、查询语言;3、扩展性和性能;4、可靠性。本专题为大家提供mongodb和mysql的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

815

5

mysql密码忘了怎么查看
mysql密码忘了怎么查看

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql密码忘了怎么办呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.19

3152

5

mysql创建数据库
mysql创建数据库

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql怎么创建数据库呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.25

5368

4

mysql默认事务隔离级别
mysql默认事务隔离级别

MySQL是一种广泛使用的关系型数据库管理系统,它支持事务处理。事务是一组数据库操作,它们作为一个逻辑单元被一起执行。为了保证事务的一致性和隔离性,MySQL提供了不同的事务隔离级别。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.08

1179

3

sqlserver和mysql区别
sqlserver和mysql区别

SQL Server和MySQL是两种广泛使用的关系型数据库管理系统。它们具有相似的功能和用途,但在某些方面存在一些显著的区别。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.11

5631

4

mysql忘记密码
mysql忘记密码

MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。那么忘记mysql密码我们该怎么解决呢?php中文网给大家带来了相关的教程以及其他关于mysql的文章,欢迎大家前来学习阅读。

2023.08.14

4902

7

mysql事务隔离级别
mysql事务隔离级别

mysql规范中定义了四种事务隔离级别,不同的隔离级别对事务的处理有所不同。本专题为大家提供mysql事务隔离级别相关的文章内容,大家可以免费体验。

2023.08.16

6534

11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL vs MySQL
PostgreSQL vs MySQL

共1课时 | 188人学习