参考:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=121&vd_source=c85b4a015a69e82ad4f202bd9b87697f

概述

介绍

锁是计算机协调多个进程或者线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU,RAM,I/O)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性,有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库而言显得尤其重要,也更见复杂。

分类

MySQL中的锁,按照锁的粒度分,分为以下三类:

1. 全局锁:锁定数据库中的所有表

2. 表级锁: 每次操作锁住整张表

3. 行级锁: 每次操作锁住对应的行数据

全局锁

介绍

全局锁就是对整个数据库实例加锁,加锁后整个实例就只处于只读状态,后续的DML的写语句,DDL语句,已经更新操作的事务提交语句都将被阻塞。其典型的使用场景是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性。

 

 

 拿到的这份备份数据,订单生成了,订单日志也有了,但tb_stock库存并没有扣减,这样就违背了数据的一致性,导致数据不一致,因此就需要加入全局锁

首先给数据库加全局锁,执行mysqldump语句进行数据备份,这时DML和DDL语句处于阻塞状态,但可以执行DQL语句,查询操作,备份完成后,拿到xxx.sql文件,就可以释放锁了

演示

flush tables with read lock; //加全局锁
mysqldump -uroot -p1234 itcast > itcast.sql  //-p后跟数据库密码,指定备份哪个数据库,> 后表示要将备份的数据存放到哪个sql文件中,执行此命令时,在系统命令行下执行,不在mysql中执行。
unlock tables;  //解锁

特点

数据库中加全局锁,是一个比较重要的操作,存在以下问题:

1. 如果在主库上备份,那么在备份期间都不能执行更新,业务基本就要停摆。

2. 如果在从库上备份,那么在备份期间从库不能执行主库同步过来的二进制文件(binlog),会导致主从延迟

在InnoDB引擎中,我们可以在备份时加上参数–single-transaction参数来完成不加锁的一致性数据备份。

如:

mysqldump --single-transaction -uroot -p123456 ltcast > Itcast.sql

表级锁

 

介绍

表级锁,每次操作锁住整张表。锁定粒度大,发生锁冲突的概率高,并发度最低。应用在MyISAM,InnoDB,BDB等存储引擎中。

对于表级锁,主要分为以下三类:

1. 表锁

2. 元数据锁(meta data lock, MDL)

3. 意向锁

表锁

对于表锁,分为两类:

1. 表共享读锁(read lock)

2. 表独占写锁(write lock)

语法:

1. 加锁: lock tables 表名… read/write

2. 释放锁: unlock tables / 客户端断开连接

 

 

 如图,客户端1加了一把读锁,不影响自己和其他客户端去读数据,但是会阻塞写操作。

 

 

 如图,客户端1加了一把写锁,自己可读可写,但其他客户端不可读不可写

元数据锁(meta data lock, MDL)

MDL加锁过程是系统自动控制。无需显式使用,在访问一张表的时候会自动加上。MDL锁主要作用是维护表元素数据的数据一致性,在表上有活动事务的时候,不可以对元数据进行写入操作。

为了避免DML与DDL冲突,保证读写的正确性。在MySQL5.5中引入了MDL,当对一张表进行增删改查的时候,加MDL读锁(共享);当对表结构进行变更操作的时候,加MDL写锁(排他)。

也可简单理解为在开启事务后crud时不能修改表结构。

 

 

 查看元数据锁

select object_type,object_schema,object_name,lock_type,lock_duration from performance_schema.metadata_locks;

意向锁

对于意向锁,分为两种:

1. 意向共享锁(IS): 由语句select…lock in share mode添加。与表锁共享锁(read)兼容,与表锁排他锁(write)互斥。

2. 意向排他锁(IX):由insert,update,delete,select…for update添加。与表锁共享锁(read)及排他锁(write)都互斥。意向锁之间不会互斥。

线程A要操作这张表,先开启事务,执行update语句,更新这张表中id为3的记录,在mysql默认的隔离级别中根据主键更新,会自动为这条数据加上行锁;

另外一个线程B要去锁这张表,加表锁,为避免与A加的行锁冲突,他要先判定这张表中有没有加行锁,以及行锁的类型来确定能不能加锁成功,这时要一行行检查行锁,性能就很低,这时就引入了意向锁。

为避免DML在执行时,加的行锁与表锁冲突,在InnoDB中引入了意向锁,使得表锁不用检查每行数据是否加锁,使用意向锁来减少表锁的检查。

有了意向锁之后

 

 

 

线程A先开启事务,执行update,先加上这一行的行锁,这时会对这张表加上意向锁;线程B这时要加上表锁,它去检查这张表的意向锁的情况,通过意向锁的情况决定它能不能加锁成功,如果意向锁与当前的锁兼容,那么直接加表锁,反之处于阻塞状态,直到A提交事务。

可以通过以下SQL,查看意向锁及行锁的加锁情况

select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks;

行级锁

介绍

行级锁,每次操作锁住对应的行数据。锁定粒度最小,发生锁冲突的概率最低,并发度最高。应用在InnoDB存储引擎中。

InnoDB的数据是基于索引组织的,行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁。对于行级锁,主要分为以下三类:

 

 

 

 

 

 

 

 简单理解:行锁+间隙锁=临键锁

InnoDB实现了以下两种类型的行锁:

1. 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁

2. 排他锁(X):允许获取排他锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁

 

 

 

 

 可以通过以下SQL,查看意向锁以及行锁的加锁情况

select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks;

执行简单的查询语句不会加锁

select * from stu where id = 1;  //不加锁
select * from stu where id = 1 lock in share mode;  //加共享锁

间隙锁/临键锁

 注意:间隙锁唯一目的是防止其他事务插入间隙。间隙锁可以共存,一个事务采用的间隙锁不会阻止另一个事务在同一间隙上使用间隙锁。

原文地址:http://www.cnblogs.com/jinci2022/p/16788861.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性