前言
前面已经介绍了原理性的内容,如果原理看的不爽,想看点实际展示效果的话,那么它来了它来了,它带着代码走来啦:blush:
基于MySQL分布式锁实现原理及代码
工欲善其事必先利其器,在基于MySQL实现分布式锁之前,我们要先了解一点MySQL锁自身的相关内容
MySQL锁
我们知道: 锁是计算机协调多个进程或者线程并发访问同一资源的机制 ,而在数据库中,除了传统的机器资源的争用之外,存储下来的数据也属于供用户共享的资源,所以如何保证数据并发的一致性,有效性是每个数据库必须解决的问题。
除此之外,锁冲突也是影响数据库并发性能的主要因素,所以锁对于数据库而言就显得非常重要,也非常复杂。
而 存储引擎 是MySQL中非常重要的底层组件,主要用来处理不同类型的SQL操作,其中包括创建,读取,删除和修改操作。在MySQL中提供了不同类型的存储引擎,根据其不同的特性提供了不同的存储机制,索引和锁功能。
根据 show engines;
能够列出MySQL下支持的存储引擎
如果没有特殊指定,那么在 MySQL8.0
中会设置 InnoDB
为默认的存储引擎
在实际工作中,根据需求选择最多的两种存储引擎分别为:
- InnoDB
- MyISAM
所以我们主要针对这两种类型来介绍MySQL的锁
InnoDB
InnoDB
支持 多粒度锁定 ,可以支持 行锁 ,也可以支持 表锁 。如果没有升级锁粒度,那么默认情况下是以行锁来设计的。
关于行锁和表锁的介绍
- 行锁对指定数据进行加锁,锁定粒度最小,开销大,加锁慢,容易出现死锁问题,出现锁冲突的概率最小,并发性最高
- 表锁对整个表进行加锁,锁定粒度大,开销小,加锁快,不会出现死锁,出现锁冲突的概率最大,并发性最低
这里没法说明那种锁最好,只有合适不合适
在行级锁中,可以分为两种类型
- 共享锁
- 排他锁
共享锁
共享锁又称为 读锁 ,允许其他 事务 读取被锁定的对象,也可以在其上获取其他共享锁,但不能写入。
举个例子:
- 事务T在数据A拥有共享锁,那么当前事务T对数据A可以读,但是不能修改。而且事务T2同样可以对数据A拥有共享锁,这样相当于在数据A上分别存在不同事务的共享锁
- 数据A拥有了事务T的共享锁,那么就不能再拥有其他事务的排他锁
下面是关于共享锁的具体实现,关键代码: select .. from table lock in share mode
-- 创建实例表 create table tb_lock( id bigint primary key auto_increment, t_name varchar(20) ) engine=InnoDB;
开启两个窗口来测试
session1 | session2 |
---|---|
set autocommit=0; | set autocommit=0; |
select * from tb_lock where t_name = 'zs' lock in share mode; | |
select * fr |