《SQL与数据库基础》16. 锁
本文以 MySQL 为例
锁
锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU、RAM、I/O)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂。
MySQL中的锁,按照锁的粒度分,分为以下三类:
- 全局锁:锁定数据库中的所有表。
- 表级锁:每次操作锁住整张表。
- 行级锁:每次操作锁住对应的行数据。
全局锁
全局锁就是对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的DML的语句,DDL语句,已经更新操作的事务提交语句都将被阻塞。
其典型的使用场景是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性。
加全局锁:
FLUSH TABLES WITH READ LOCK;
释放锁:
UNLOCK TABLES;
数据备份(Windows命令):
mysqldump [-h 数据库主机地址] -u用户 -p密码 要备份的数据库 > 保存路径及备份文件名.sql
数据备份的相关指令,在MySQL管理章节还会详细介绍
数据库中加全局锁,是一个比较重的操作,存在以下问题:
- 如果在主库上备份,那么在备份期间都不能执行更新,业务基本上就得停摆。
- 如果在从库上备份,那么在备份期间从库不能执行主库同步过来的二进制日志(binlog),会导致主从延迟。
在InnoDB引擎中,我们可以在备份时加上参数 --single-transaction 参数来完成不加锁的一致性数据备份。
mysqldump --single-transaction [-h 数据库主机地址] -u用户 -p密码 要备份的数据库 > 保存路径及备份文件名.sql
表级锁
表级锁,每次操作锁住整张表。锁定粒度大,发生锁冲突的概率最高,并发度最低。应用在MyISAM、InnoDB、BDB等存储引擎中。
对于表级锁,主要分为以下三类:
- 表锁
- 元数据锁(meta data lock,MDL)
- 意向锁
表锁
对于表锁,分为两类:
- 表共享读锁(read lock)
- 表独占写锁(write lock)
读锁不会阻塞其他客户端的读,但是会阻塞写,也会阻塞当前客户端的写。
写锁既会阻塞其他客户端的读,又会阻塞其他客户端的写。
锁类型:READ,WRITE
加锁:
LOCK TABLES 表名 锁类型;
释放锁:
UNLOCK TABLES;
客户端断开连接会自动释放锁。
元数据锁
meta data lock,元数据锁,简写MDL。
MDL加锁过程是系统自动控制,无需显式使用,在访问一张表的时候会自动加上。MDL锁主要作用是维护表元数据的数据一致性,在表上有活动事务的时候,不可以对元数据进行写入操作。为了避免DML与DDL冲突,保证读写的正确性。
这里的元数据,可以简单理解为一张表的表结构。也就是说,某一张表涉及到未提交的事务时,不能修改这张表的表结构。
在MySQL5.5中引入了MDL,当对一张表进行增删改查的时候,加MDL读锁(共享);对表结构进行变更操作的时候,加MDL写锁(排他)。
常见的SQL操作时,所添加的元数据锁:
| 对应SQL | 锁类型 | 说明 |
|---|---|---|
| lock tables 表名 锁类型 | SHARED_READ_ONLY / SHARED_NO_READ_WRITE | |
| select、select ... lock in share mode | SHARED_READ | 与SHARED_READ、SHARED_WRITE兼容,与EXCLUSIVE互斥 |
| insert、update、delete、select ... for update | SHARED_WRITE | 与SHARED_READ、SHARED_WRITE兼容,与EXCLUSIVE互斥 |
| alter table ... | EXCLUSIVE | 与其他的MDL都互斥 |
查看元数据锁加锁情况:
SELECT object_type, object_schema, object_name, lock_type, lock_duration FROM performance_schema.metadata_locks;
意向锁
为了避免DML在执行时,加的行锁与表锁的冲突,在InnoDB中引入了意向锁,使得表锁不用检查每行数据是否加锁,使用意向锁来减少表锁的检查。
意向锁分类:
- 意向共享锁(IS)
由语句 select ... lock in share mode 添加 。与表锁共享锁(read)兼容,与表锁排他锁(write)互斥。 - 意向排他锁(IX)
由insert、update、delete、select ... for update 添加。与表锁共享锁(read)及排他锁(write)都互斥,意向锁之间不会互斥。
一旦事务提交了,意向共享锁、意向排他锁都会自动释放。
查看意向锁及行锁加锁情况:
SELECT object_schema, object_name, index_name, lock_type, lock_mode, lock_data FROM performance_schema.data_locks;
行级锁
行级锁,每次操作锁住对应的行数据。锁定粒度最小,发生锁冲突的概率最低,并发度最高。应用在InnoDB存储引擎中。
InnoDB的数据是基于索引组织的,行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁。
对于行级锁,主要分为以下三类:
- 行锁(Record Lock)
锁定单个行记录的锁,防止其他事务对此行进行 update 和 delete。在RC、RR隔离级别下都支持。 - 间隙锁(Gap Lock)
锁定索引记录间隙(不含该记录),确保索引记录间隙不变,防止其他事务在这个间隙进行 insert,产生幻读。在RR隔离级别下都支持。 - 临键锁(Next-Key Lock)
行锁和间隙锁组合,同时锁住数据,并锁住数据前面的所有间隙。在RR隔离级别下支持。
行锁
行锁,也叫记录锁。InnoDB实现了两种类型的行锁:
- 共享锁(S)
允许一个事务去读一行,阻止其他事务获得相同数据集的排它锁。 - 排他锁(X)
允许获取排他锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁。
两种行锁的兼容情况如下:

常见的SQL语句,在执行时,所加的行锁如下:
| SQL | 行锁类型 | 说明 |
|---|---|---|
| INSERT ... | 排他锁 | 自动加锁 |
| UPDATE ... | 排他锁 | 自动加锁 |
| DELETE ... | 排他锁 | 自动加锁 |
| SELECT(正常) | 不加任何锁 | |
| SELECT ... LOCK IN SHARE MODE | 共享锁 | 需要手动在SELECT之后加LOCK IN SHARE MODE |
| SELECT ... FOR UPDATE | 排他锁 | 需要手动在SELECT之后加FOR UPDATE |
默认情况下,InnoDB在 REPEATABLE READ 事务隔离级别运行,InnoDB使用 next-key 锁进行搜索和索引扫描,以防止幻读。
- 针对唯一索引进行检索时,对已存在的记录进行等值匹配时,将会自动优化为行锁。
- InnoDB的行锁是针对于索引加的锁,不通过索引条件检索数据,那么InnoDB将对表中的所有记录加锁,此时就会升级为表锁。
查看意向锁及行锁的加锁情况:
SELECT object_schema,object_name,index_name,lock_type,lock_mode,lock_data FROM performance_schema.data_locks;
间隙锁
默认情况下,InnoDB在 REPEATABLE READ 事务隔离级别运行,InnoDB使用 next-key 锁进行搜索和索引扫描,以防止幻读。
- 索引上的等值查询(唯一索引),给不存在的记录加锁时,优化为间隙锁。
- 索引上的等值查询(非唯一普通索引),向右遍历时最后一个值不满足查询需求时,next-key lock 退化为间隙锁。
- 索引上的范围查询(唯一索引)会访问到不满足条件的第一个值为止。
间隙锁唯一目的是防止其他事务插入间隙。间隙锁可以共存,一个事务采用的间隙锁不会阻止另一个事务在同一间隙上采用间隙锁。
临键锁
临键锁,是记录锁与间隙锁的组合,它的封锁范围,既包含索引记录,又包含索引区间。
临键锁的主要目的,也是为了避免幻读(Phantom Read)。如果把事务的隔离级别降级为RC,临键锁则也会失效。
《SQL与数据库基础》16. 锁的更多相关文章
- C#面试题(转载) SQL Server 数据库基础笔记分享(下) SQL Server 数据库基础笔记分享(上) Asp.Net MVC4中的全局过滤器 C#语法——泛型的多种应用
C#面试题(转载) 原文地址:100道C#面试题(.net开发人员必备) https://blog.csdn.net/u013519551/article/details/51220841 1. . ...
- Sql Server数据库基础
--------------------------------------第一章 Sql Server数据库基础------------------------------------------ ...
- SQL Server 数据库基础笔记分享(下)
前言 本文是个人学习SQL Server 数据库时的以往笔记的整理,内容主要是对数据库的基本增删改查的SQL语句操作和约束,视图,存储过程,触发器的基本了解. 注:内容比较基础,适合入门者对SQL S ...
- sql Servers数据库基础
1. 数据库约束包含: ·非空约束 ·主键约束(PK) primary key constraint 唯一且不为空 ·唯一约束(UQ) unique constraint 唯一 ...
- SQL Server 数据库基础笔记分享(上)
前言 本文是个人学习SQL Server 数据库时的以往笔记的整理,内容主要是对数据库的基本增删改查的SQL语句操作和约束,视图,存储过程,触发器的基本了解. 注:内容比较基础,适合入门者对SQL S ...
- Sql Server 数据库事务与锁,同一事务更新又查询锁?期望大家来解惑
我有一个People表,有三行数据: 如果我们没详细了解数据库事务执行加锁的过程中,会不会有这样一个疑问:如下的这段 SQL 开启了事务,并且在事务中进行了更新和查询操作. BEGIN TRAN up ...
- DBA常用SQL之数据库基础信息
第一部分: 1. 查看oracle最大连接数 sql>show parameter processes #最大连接数 2. 修改最大连接数 sql>alter system set pro ...
- sql server 数据库基础知识(二)
CASE函数用法1:单值判断,相当于switch caseCASE expression WHEN value1 THEN returnvalue1 WHEN value2 THEN returnva ...
- 【2017-03-09】SQL Server 数据库基础、四种约束
一.数据库和内存的区别 数据库:一些存储在硬盘上的数据文件 内存:计算机临时存储的一些数据 二.常用数据库 .Net - SQL Server PHP - MySql Java - Oreacl 三. ...
- SQL Server数据库基础笔记
启动和停止SQL Server服务三种形式 后台启动服务 计算机->右键->管理->服务和应用程序->服务->sql server(MSSQLSERVER) SQL Se ...
随机推荐
- SQL Server:User, group, or role 'iemis' already exists in the current database.
--最新的解决方法 --先创建用户帐户,不进行授权,然后通过下面的SQL语句将该用户帐户关联至对应的数据库用户.优点是避免了重新授权的操作. USE tempdbEXEC sp_change_user ...
- 数学建模 Excel的批量写入与批量导出
数学建模中编程手们常常会被要求将大量的数据进行批量的预测操作,并写入某个文件中 Excel的批量导出数据,用循环就可以简单实现,例如 import pandas as pd for i in list ...
- python如何利用算法解决业务上的【分单问题】
分单是很多企业日常工作中非常典型的一项内容,它非常复杂,但同时又极为重要,如何合理的分单是企业管理中一个很重要的课题. 之所以说分单很复杂,是因为影响单据该分给谁,分多少量这个事儿本身就有太多的影响因 ...
- C#识别文字内容并分类输出0和1
这个代码最开始是为了处理在调查问卷的结果,问卷星等调查问卷有一部分是用汉字描述的多选题,问卷系统在输出问卷的时候直接就是将汉字进行输出,而我们在进行数据分析(二元logistic或多项logistic ...
- UpSetR 高级参数使用教程
在<UpSetR:多数据集绘图可视化处理利器>中我们介绍了 UpSetR 的一些概念和绘图基础参数使用,今天我们来学习一下 UpSetR 的 queries 和 attribute.plo ...
- Java拓展-拆,装箱,线程,反射
导言: 在学习JavaSE的时候,我们会使用Java基础编程,并且了解了什么是面向对象的编程,会使用Java写一些基础算法程序, 接下来,我们需要了解Java的自动拆箱和自动装箱,单线程和多线程,反射 ...
- React后台管理系统11 配置项目初始化展开代码
在上一文中,我们已经配置好了,刷新默认打开选中的样式,但是如果是在/page3/1,这种的,并没有选中到/page3里面的/page3/1,这个地方来,所以我们需要解决的就是这几个问题: 思路如下: ...
- 获取邮箱(QQ、126、163)的客户端授权码
获取QQ邮箱的客户端授权码 1.首先登录QQ邮箱(https://mail.qq.com),然后,点击"设置"按钮. 2.点击"账户"按钮,进入"账户 ...
- 怎么把 session 中的实体类转换回来
例子 : 如上比如user user1=new user(): user1.id=1: user1.name="张三": session["user1"]=us ...
- matlab gui .mat数据读取
在matlab的gui中用load函数读取.mat等类型数据 %定义全局变量 global img_correct %读取数据名称及位置 [filename,pathname]=uigetfile({ ...