网站设计版式,html个人博客完整代码,网络平台推广,游戏小程序开发需要多少资本目录
前言
全局锁
表级锁
表锁
元数据锁#xff08;MDL#xff09;
意向锁
行级锁
行锁
行锁演示
间隙锁/临界锁
演示 前言
MySQL中的锁#xff0c;按照锁的粒度分#xff0c;分为以下三类
全局锁#xff1a;锁定数据库中的所有表。表级锁#xff1a;每次操…目录
前言
全局锁
表级锁
表锁
元数据锁MDL
意向锁
行级锁
行锁
行锁演示
间隙锁/临界锁
演示 前言
MySQL中的锁按照锁的粒度分分为以下三类
全局锁锁定数据库中的所有表。表级锁每次操作锁住整张表。行级锁每次操作锁住对应的行数据。
全局锁
全局锁就是对整个数据库实例加锁加锁后整个实例就处于只读状态后续的DML的写语句DDL语句以及更新操作的事务提交语句都将被阻塞。
其典型的使用场景是做全库的逻辑备份对所有的表进行锁定从而获取一致性视图保证数据的完整性。 具体语句为 -- 添加全局锁
flush tables with read lock;
-- 开始备份
mysqldump -r用户名 -p密码 数据库名保存文件名称.sql
-- 解锁
unlock tables;
全局锁特点
如果没有做主从分离那么在备份期间不能执行更新操作业务基本停摆。做了主从分离后可以选择在从库上备份在备份期间从库不能执行主库同步过来的二进制日志(binlog)导致主从延迟。
但也存在不阻塞而是基于快照就可以实现备份的语句
mysqldump --single-transaction -u用户名 -p密码 数据库名保存的文件名称.sql
表级锁
每次操作所著整张表锁定粒度大发生所冲突的概率最高并发度最低。
对于表级锁主要分为以下三类
表锁元数据锁意向锁
表锁
对于表锁又可以分为两类
表共享读锁read lock表独占写锁write lock 基本语法 -- 加锁
lock tables 表名… read/write;
-- 释放锁
unlock tables / 客户端断开连接
读锁特点
自身以及其他客户端的读操作可以正常执行。自身执行写操作会报错其他客户端执行写操作会阻塞。
写锁特点
自身既可以读也可以写。其他客户端不能读也不能写会直接阻塞。
元数据锁MDL
MDL加锁过程是系统自动控制无需显式使用在访问一张表的时候会自动加上。MDL锁主要作用是维护表元数据的数据一致性在表上有活动事务的时候不可以对元数据进行写入操作。主要是为了避免DML与DDL冲突保证读写的正确性。
在MySQL5.5中引入了MDL当对一张表进行增删改查的时候加MDL读锁(共享当对表结构进行变更操作的时候加MDL写锁(排他。 对应SQL 锁类型 select SHARED_READ insert、update、delete SHARED_WRITE alter table EXCLUSIVE
共享读与共享写都属于共享锁他们两个互相兼容并于排他锁互斥。 查看数据库中元数据锁信息 select object_type,object_schema,object_name,lock_type,lock_duration from performance_schema.metadata_locks ;
意向锁
意向锁是为了避免DML数据库操作语句在执行过程中出现行锁与表锁的冲突通过意向锁可以在创建表锁时不需要去检查每行数据是否有行锁从而减少表锁检查所带来的性能消耗。
没有使用意向锁之前客户端A给表中加了行锁客户端B要给表加表锁过程如下 首先客户端A开启一个事务在事务中对表中的数据进行增删改查在执行增删改时会对表中的这些数据加一个行锁这时客户端B想在表中添加一个表锁客户端B在添加表锁前先会去检查当前表中每一行数据是否有行锁如果没有则会去添加表锁。 也就是说不使用意向锁的话。客户端向表加锁需要遍历整张表当表数据量很大时效率很低。
当有了意向锁之后客户端A给表中加了行锁客户端B要给表加表锁过程如下 首先客户端A开启一个事务在事务中对表的数据进行增删改查对数据添加行锁的同时又会给表添加一个意向锁这时客户端B想要在表中添加一个表锁客户端B就会根据客户端A加的意向锁来判断是否可以成功添加表锁并且不会再逐行检查数据是否有行锁效率得到大幅度提升。 简单来说意向锁相当于一个声明而不是一个真正的锁根据这个声明添加表锁时就有了参考依据因此不需要逐行判断是否可以添加表锁从而避免了行锁与表锁产生的冲突。
意向锁的分类
意向共享锁IS平常的select语句不会自定添加意向共享锁需要在select后面加上lock in share mode参数才能为表建立意向共享锁。意向排它锁IXinsert、update、delete、select…for update等语句都会字段添加一个意向排它锁。
意向共享锁可以与表锁中表共享读锁read兼容但是与表锁中的表独占写锁write互斥当表中存在一个意向共享锁时我们可以为表正常设置一个读锁但是不能设置为写锁当为表设置写锁时就会处于阻塞状态只有当事务提交后写锁才能正常执行。
意向排它锁既与表共享读锁排斥又与表独占写锁排斥当表中有意向排它锁时即不可以设置表读锁也不可以设置为表写锁。
当事务提交后意向共享锁、意向排它锁都自己释放锁说是释放其实可以理解为将标记清空被阻塞的操作此时才能被执行。
行级锁
行级锁每次操作锁住对应的行数据。锁定粒度最小发生锁冲突的概率最低并发度最高。应用在InnoDB存储引擎中。
InnoDB的数据是基于索引组织的行锁是通过对索引上的索引项加锁来实现的而不是对记录加的锁。对于行级锁主要分为以下三类 行锁(Record Lock)锁定单个行记录的锁防止其他事务对此行进行update和delete。在读已提交、可重复读隔离级别下都支持 间隙锁(Gap Lock)锁定索引记录间隙(不含该记录)确保索引记录间隙不变防止其他事务在这个间隙进行insert产生幻读。在可重复读隔离级别下都支持 临键锁(Next-Key Lock)行锁和间隙锁组合同时锁住数据并锁住数据前面的间隙Gap。在可重复读隔离级别下支持。 行锁
InnoDB实现了以下两种类型的行锁
共享锁(S)允许一个事务去读一行阻止其他事务获得相同数据集的排它锁。排他锁(X)允许获取排他锁的事务更新数据阻止其他事务获得相同数据集的共享锁和排他锁。
锁兼容情况如下 共享锁 排他锁 共享锁 兼容 互斥 排他锁 互斥 互斥
加锁情况如下 SQL 行锁类型 说明 insert 排他锁 自动加锁 update 排他锁 自动加锁 delete 排他锁 自动加锁 select 不加锁 select……lock in share mode 共享锁 需要手动在select之后添加local in share mode select ……for update 排他锁 需要手动在select之后加for update
行锁演示
默认情况下lnnoDB在可重复读事务隔离级别运行InnoDB使用临键锁进行搜索和索引扫描以防止幻读。
针对唯一索引进行检索时对已存在的记录进行等值匹配时将会自动优化为行锁。InnoDB的行锁是针对于索引加的锁不通过索引条件检索数据那么InnoDB将对表中的所有记录加锁此时就会升级为表锁 查看行锁情况的SQL语句 select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks ; 现在存在一个主键为id的user表username没有创建索引 在一个客户端开启事务并进行查询。另一个客户端查看行锁数据 此时我们可以看到MySQL没有对select语句进行加锁。接下来我们手动对select语句加锁 由于行锁中的共享锁是互相兼容的因此我也可以再另一个客户端进行select语句此时锁记录表中出现两条锁记录。 当事务提交后事务涉及到锁也会释放 接下来我们测试update语句 接下来测试对非索引的字段进行条件判断观察添加的是什么锁 因此我们可以知道当对没有索引的字段进行条件查询时行级锁会升级为表锁。
间隙锁/临界锁
默认情况下InnoDB在可重复读事务隔离级别运行lnnoDB使用间隙锁锁进行搜索和索引扫描以防止幻读。
索引上的等值查询(唯一索引)给不存在的记录加锁时,优化为间隙锁。索引上的等值查询(普通索引)向右遍历时最后一个值不满足查询需求时临键锁退化为间隙锁索引上的范围查询(唯一索引)会访问到不满足条件的第一个值为止。
注意间隙锁唯一目的是防止其他事务插入间隙。间隙锁可以共存一个事务采用的间隙锁不会阻止另一个事务在同一间隙上采用间隙锁。
演示 展示第一种情况给不存在的记录加锁。 加下来展示第二种情况我添加了一个age字段并创建了普通索引 另一个客户端插入对应被锁住的范围时会阻塞而插入其他范围可以正常执行。 接下来展示第三种情况对唯一索引的范围查找。