目录
介绍
分类
1、全局锁
1.1介绍
1.2场景
1.3语法
1.4演示
2、表级锁
2.1介绍
2.2分类
2.3语法
2.4演示
3、行级锁
3.1介绍
3.2分类
3.3场景
介绍
锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU、RAM、I/O)等争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。
分类
MySQL中的锁按照粒度可以分为以下三类:
1、全局锁:锁定数据库中所有表;
2、表级锁:每次操作锁住整张表;
3、行级锁:每次操作锁住对应的行数据;
1、全局锁
1.1介绍
全局锁就是对整个数据库实例加锁,加锁后整个数据库实例处于只读状态,提交的写入、更新、删除操作语句都会被阻塞。
最典型的使用场景就是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性。
1.2场景
假如数据库中有三张表,分别是商品库存表、订单表、订单记录表,如果对数据库直接进行备份,当商品库存表备份完成继续执行后续备份时,有客户下单会使三张表数据都进行改变,导致备份的商品库存表是该客户下单前的数据,订单表和订单记录表时该客户下单后的数据,此时备份完成的数据就不完整,不一致。
1.3语法
实现加全局锁进行逻辑备份主要分为以下步骤:
1、flush tables with read lock; 加全局锁;
2、mysqldump -u账户 -p密码 数据库名 > 备份sql文件路径 进行备份;
3、unlock tables; 释放全局锁;
1.4演示
连接数据库:我使用的本地数据库,如测试远程数据库可使用 mysql -h IP地址 -u 账号 -p 密码 连接;
加全局锁:所有数据库表全部锁住;
测试读写语句:此时数据库处于只读状态,更新、写入、删除语句都被不生效;
备份:因为该命令不是sql命令,所以需要退出mysql直接在命令窗口执行即可;
释放锁:
2、表级锁
2.1介绍
表级锁,每次操作锁住整张表,锁粒度最大,发生锁冲突的概率最高,并发最低,
2.2分类
对于表级锁,主要分为以下三类:
1.表锁;对于表锁可以分为两类:
1.1表共享读锁:加锁后只能读数据,不能更新、写入、删除数据,并且其他客户端访问也只能读数据,不能更新、写入、删除数据;
1.2表独占写锁:加锁后可以读、更新、写入、删除数据,但其他客户端访问不能读、更新、写入、删除数据;
2.元数据锁(MDL):元数据锁的加锁过程是系统自动控制的,无需显示使用,在访问一张表的时候会自动加上,元数据锁主要作用是维护表元数据的数据一致性,在表上有活动事务的时候,不可以对元数据进行写入操作。为了避免DDL与DML冲突,保证读写的正确性。
说明:元数据其实就是表的结构,元数据锁就是用来保证表结构的一致性,比如当某张表上有未提交的事务时,系统会自动加锁,该期间不能改变表的结构。
在MySQL5.5中引入了元数据锁,当对一张表进行增删改查的时候,自动加MDL读锁,当对表的结构进行变更操作的时候,自动加MDL写锁。
3.意向锁:为了避免DML语句执行时,加的行锁与表锁冲突,在InnoDB中引入了意向锁,使得表锁不用检查每行数据是否有行锁,使用意向锁来减少表锁的检查。意向锁可分为两类:
3.1意向共享锁(IS):与表锁共享读锁兼容,与表锁独占写锁互斥;
3.2意向排他锁(IX):与表锁共享读锁和表锁独占写锁都互斥;意向锁之间不会互斥;
说明:线程A开启事务,执行更新语句更新第五行数据,于是第五行数据会加上行锁,此时线程B进来准备对该表加表锁,线程B加表锁前会检查该表每行数据是否有行锁及类型,于是就会从第一行挨个检查,这个时候检查的效率就会极低。当引入了意向锁之后就会变成这样的情况,线程A开启事务,执行更新语句更新第五行数据,于是第五行数据会加上行锁同时对该表加上意向锁,此时线程B进来准备对该表加表锁,此时检查的是该表是否有意向锁而不是每行检查行锁,发现意向锁之后线程B被阻塞,知道线程A提交事务结束线程B继续执行任务。
2.3语法
表锁
加锁:lock tables 表名... read/write;
释放锁:unlock tables/客户端断开连接;
2.4演示
表共享读锁:客户端1进行加锁,加锁后客户端1只能读数据,不能操作数据,客户端2只能读数据,操作数据会被阻塞,直到客户端1释放锁,客户端2的操作数据语句才会继续执行;
表独占写锁:客户端1加锁后,可以进行读写数据操作,客户端2的读写操作都会被阻塞,直到客户端1将锁释放才会继续执行;
元数据库锁:在客户端1开始事务,执行查询语句且不提交事务,然后在客户端2中修改表结构会被阻塞,直到客户端1提交事务后,客户端2的修改表结构语句才会继续执行。
意向共享锁:select语句需手动加上 lock in share mode 才会加上行锁和意向共享锁;
意向排他锁:update、delete、insert语句执行时会自动加行锁和意向排他锁;
3、行级锁
3.1介绍
行级锁每次操作锁住对应的行数据,锁粒度最小,发生锁冲突的概率最低,并发度最高,主要应用在InnoDB存储引擎中。
3.2分类
InnoDB的数据是基于索引组织的,行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁。行级锁主要分为以下三类:
1.行锁:锁定单个行记录的锁,防止其他事务对此进行update和delete,在RC、RR隔离级别下都支持;行锁分为以下两类:
1.1共享锁(S):允许一个事务去读一行,阻止其他事务获取相同数据的排他锁(共享锁与共享锁兼容,共享锁与排他锁互斥);
1.2排他锁(X):允许获取排他锁的事务更新数据,阻止其他事务获取相同数据的共享锁和排它锁(排他锁与共享锁互斥,排他锁与排他锁互斥);
2.间隙锁:锁定索引记录间隙,不包含记录,确保索引记录间隙不变,防止其他事务在这个间隙进行insert,在RR隔离级别下支持;
3.临键锁:行锁和间隙锁的组合,同时锁住数据和数据前面的所有间隙,在RR隔离级别下支持;
3.3场景
行锁
InnoDB的行锁是针对索引加的锁,当不通过索引条件操作数据时,那么InnoDB会将表中所有记录加锁,此时就会升级为表锁;
SQL | 行锁类型 | 说明 |
---|---|---|
INSERT... | 排他锁 | 自动加锁 |
UPDATE... | 排他锁 | 自动加锁 |
DELETE... | 排他锁 | 自动加锁 |
SELECT... | 不加任何锁 | |
SELECT... LOCK IN SHAR MODE | 共享锁 | 需手动在SELECT后加LOCK IN SHAR MODE |
SELECT... FOR UPDATE | 排他锁 | 需手动在SELECT后加FOR UPDATE |