数据库的锁——思想概念篇

简介: 数据库的锁——思想概念篇

数据库的锁——思想概念篇


文章目录

数据库的锁

锁是数据库系统区别于文件系统的一个关键特性,锁机制用于管理对共享资源的并发访问。

下面我们以MySQL数据库的InnoDB引擎为例,来说明锁的一些特点。

锁的类型:

InnoDB存储引擎实现了如下两种标准的行级锁:

  • 共享锁(S Lock),允许事务读一行数据
  • 排他锁(X Lock),允许事务删除或更新一行数据

例如:如果一个事务T1已经获得了行 r 的共享锁,那么另外的事务T2可以立即获得 行r 的共享锁,因为读取并没有改变行r的数据,称这种情况为锁兼容。但若有其他的事务T3想获得 行r 的排他锁,则其必须等待事务T1、T2释放行 r 上的共享锁,这种情况称为锁不兼容

下图显示了共享锁和排他锁的兼容性,可以发现X锁与任何的锁都不兼容,而S锁仅和S锁兼容。

需要特别注意的是,S和X锁都是行锁,兼容是指对同一记录(row)锁的兼容性情况。

锁的粒度:

InnoDB存储引擎支持多粒度锁定,这种锁定允许事务在行级上的锁和表级上的锁同时存在。

为了支持在不同粒度上进行加锁操作,InnoDB存储引擎支持一种额外的锁方式,称之为意向锁。意向锁是将锁定的对象分为多个层次,意向锁意味着事务希望在更细粒度上进行加锁

InnoDB存储引擎支持意向锁设计比较简练,其意向锁即为表级别的锁。设计目的主要是为了在一个事务中揭示下一行将被请求的锁类型。

其支持两种意向锁:

  • 意向共享锁(IS Lock),事务想要获得一张表中某几行的共享锁
  • 意向排他锁(IX Lock),事务想要获得一张表中某几行的排他锁

由于InnoDB存储引擎支持的是行级别的锁,因此意向锁其实不会阻塞除全表扫以外的任何请求。

故表级意向锁与行级锁的兼容性如下图所示:

锁的算法:

InnoDB存储引擎有3种行锁的算法,其分别是:

1. 行锁(Record Locks)

行锁,顾名思义,就是只会锁住某一行的数据,行级锁能大大减少数据库操作的冲突。

其加锁粒度最小,但加锁的开销也最大。有可能会出现死锁的情况。产生行锁一般是等值查询,且作用于唯一索引或连续的普通索引(普通索引列的值没有间隔)

※ InnoDB中行级锁是怎么实现的?

InnoDB行级锁是通过给索引上的索引项加锁来实现的

只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁。当表中锁定其中的某几行时,不同的事务可以使用不同的索引锁定不同的行。另外,不论使用主键索引、唯一索引还是普通索引,InnoDB都会使用行锁来对数据加锁。

2. 间隙锁(Gap Locks)

间隙锁是封锁索引记录中的间隔,或者第一条索引记录之前的范围,又或者最后一条索引记录之后的范围(不包括记录本身)

可能产生间隙锁的条件:

  1. 使用普通索引锁定;
  2. 使用多列唯一索引;
  3. 使用唯一索引锁定多行记录。

间隙锁可以通过参数innodb_locks_unsafe_for_binlog开闭,它的作用是为了阻止多个事务将记录插入到同一范围内,而这会导致幻读问题的产生。

3. 临键锁(Next-key Locks)

临键锁是行锁和间隙锁的组合,它的封锁范围,既包含索引记录本身(行锁),又包含索引区间(间隙锁)

无论是唯一索引或是普通索引都有可能产生临键锁。

RR隔离级别,默认是临键锁,临键锁根据不同的作用范围,可以转换为行锁和间隙锁,在RC隔离级别下,它和间隙锁会失效。

关于死锁:

死锁是指两个或两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象。若无外力作用,事务都将无法推进下去

比如说:事务A等待事务B、事务B等待事务A,这种死锁问题被称为AB-BA死锁,下图演示了死锁的这一种经典的情况:

解决死锁:

方法一: 解决死锁问题最简单的一种方法是超时,即当两个事务互相等待时,当一个等待时间超过设置的某一阈值时,其中一个事务进行回滚,另一个等待的事务就能继续进行

方法二:除了超时机制,当前数据库还都普遍采用 wait-for graph(等待图)的方式来进行死锁检测。较之超时的解决方案,这是一种更为主动的死锁检测方式。InnoDB存储引擎也采用的这种方式。

wait-for graph(等待图)要求数据库保存以下两种信息:

  • 锁的信息链表;
  • 事务等待链表;

通过上述链表可以构造出一张图,而在这个图中若存在回路,就代表存在死锁,因此资源间相互发生等待。这是一种较为主动的死锁检测机制,在每个事务请求锁并发生等待时都会判断是否存在回路,若存在则有死锁,通常来说InnoDB存储引擎选择回滚undo量最小的事务

比如下图就很形象,事务T1,T2,T3发生了死锁,InnoDB中存储的锁与事务链表构成的等待图就会发生回路,此时就能检测到死锁发生,然后InnoDB就会回滚事务。

锁的升级:

锁升级(Lock Escalation)是指将当前锁的粒度降低

举例来说,数据库可以把一个表的1000个行锁升级为一个页锁,或者将页锁升级为表锁。

InnoDB存储引擎不存在锁升级的问题。因为其不是根据每个记录来产生行锁的,相反,InnoDB存储引擎是根据每个事务访问的每个页对锁进行管理的,采用的是位图的方式。因此不管一个事务锁住页中一个记录还是多个记录,其开销通常都是一致的。


相关文章
|
4天前
|
存储 数据采集 数据管理
什么是数据库的概念模式
什么是数据库的概念模式
26 5
|
5天前
|
SQL Oracle 关系型数据库
数据库SQL语言实战(五)(数据库系统概念第三章练习题)
本文的SQL语言适用的是Oracle数据库与mySQL可能存在略微不同
|
5天前
|
SQL Oracle 关系型数据库
数据库SQL语言实战(四)(数据库系统概念第三章练习题)
本文的SQL语言适用的是Oracle数据库与mySQL可能存在略微不同
数据库SQL语言实战(四)(数据库系统概念第三章练习题)
|
5天前
|
存储 算法 搜索推荐
矢量数据库基础:概念、原理与应用场景
【4月更文挑战第30天】矢量数据库,处理高维向量数据的工具,应用于GIS、推荐系统、图像搜索及语义搜索。核心原理是将原始数据嵌入到高维空间,通过索引算法优化搜索性能。现代深度学习模型如Word2Vec提升向量表示准确性,KD-Tree、LSH等算法加速相似性搜索。随着技术发展,矢量数据库在数据科学领域的重要性日益增强。
|
5天前
|
SQL Oracle 安全
Oracle数据库中的事务和锁
【4月更文挑战第19天】Oracle数据库的事务和锁是确保数据完整性和并发控制的核心机制。事务遵循ACID原则,保证操作的原子性、一致性、隔离性和持久性。通过COMMIT或ROLLBACK来管理事务更改。锁包括共享锁(读)、排他锁(写)、行级锁和表级锁,用于控制并发访问。自动锁机制在DML操作时生效,防止数据冲突。事务和锁共同维护数据库的稳定和安全。
|
5天前
|
关系型数据库 MySQL 数据库
【后端面经】【数据库与MySQL】12|数据库锁:明明有行锁,怎么突然就加了表锁?
【4月更文挑战第15天】在MySQL的InnoDB引擎中,锁通过索引实现,主要锁定叶子节点。查询使用哪个索引,就锁哪个;无索引时锁全表。若查询值不存在,InnoDB会构造临键锁阻止插入。锁在事务结束(Rollback或Commit)时释放。乐观锁在尝试更新时检查数据变化,适合读多写少场景,悲观锁一开始就加锁,适用于写多读少。InnoDB支持行锁和表锁,行锁依赖索引。共享锁允许多个线程加同类型锁,排它锁则独占。
45 1
|
5天前
|
SQL 算法 数据库
数据库系统概念(第三周 第一二堂总结)
数据库系统概念(第三周 第一二堂总结)
|
5天前
|
机器学习/深度学习 数据可视化 安全
数据库系统概念(第二周 第二堂)(关系模型)
数据库系统概念(第二周 第二堂)(关系模型)
|
5天前
|
SQL 存储 前端开发
数据库系统概念(第二周 第一堂)
数据库系统概念(第二周 第一堂)
|
5天前
|
存储 数据可视化 安全
数据库系统概念(第一周)
数据库系统概念(第一周)