(MySQL)分布式锁
在分布式系统中,多个进程可能会同时对同一资源进行操作,如果没有同步机制,就会造成数据不一致问题。为了避免这种情况,需要分布式锁。Redis 是常见的实现方式,但在某些场景下,我们也可以使用 MySQL 来实现分布式锁。
一、MySQL 实现分布式锁的方式
1. 基于 SELECT ... FOR UPDATE
在数据库中设计一张锁表,例如
lock_table
,其中包含resource
字段表示锁的资源。当某个进程想要获取锁时,它执行一条带有事务的
select ... for update
语句,查询指定的resource
。由于
for update
会对该行加行级排他锁,因此同一时间只有一个事务能够获取成功。业务执行完后,提交事务,释放锁。
这种方式依赖 事务 + 行锁,实现简单,但如果事务未提交,锁就会一直被持有,可能导致阻塞。
2. 基于唯一索引插入
在数据库中建立一张锁表,
resource
字段设置为唯一索引。当进程尝试获取锁时,插入一条
resource = xxx
的记录:如果插入成功,说明锁获取成功。
如果插入失败(因为唯一约束冲突),说明锁已被占用。
释放锁时,删除对应的
resource
记录。
这种方式实现的是 非阻塞锁,适合对性能有一定要求的场景。
二、存在的问题
性能较低:相比 Redis 内存操作,MySQL 的锁实现基于磁盘/事务,效率偏低。
死锁风险:如果事务未提交或连接异常,可能导致锁长时间不释放。
可扩展性差:MySQL 适合小规模场景,一旦分布式规模扩大,性能瓶颈明显。
三、适用场景
对一致性要求极高的场景,可以用 MySQL 锁来保证严格的事务隔离。
数据规模和并发量不大,且业务已经高度依赖 MySQL 的情况下。
四、总结
MySQL 分布式锁的两种实现方式:
基于事务的
select ... for update
(阻塞锁)基于唯一索引插入(非阻塞锁)
虽然可以用 MySQL 实现分布式锁,但实际生产环境更多推荐 Redis 或 ZooKeeper,因为它们在 性能、可用性和可靠性 上更适合大规模分布式场景。