首页 > 数据库 >数据库的锁和MVCC机制

数据库的锁和MVCC机制

时间:2023-12-06 10:55:25浏览次数:35  
标签:事务 记录 数据库 并发 MVCC 操作 机制 数据

数据库的锁机制,是数据库为了保证数据的一致性和完整性,使各种共享资源在被并发访问时变得有序所设计的一种规则。

之前讲到过事务,提到事务的ACID原则 和 隔离的级别
一条SQL的背后故事(三)

目前较为常见的三种并发控制机制:分别是悲观并发控制(锁)、乐观并发控制(乐观锁)和多版本并发控制(MVCC)

悲观并发控制
在悲观并发控制中,数据库程序对于数据被修改持悲观的态度,在数据处理的过程中都会被锁定,以此来解决竞争的问题。

此处大量引用 数据库基础(三)Mysql里的锁

基于锁的属性分类:共享锁、排他锁。
基于锁的粒度分类:表锁、行锁、记录锁、间隙锁、临键锁。
基于锁的状态分类:意向共享锁、意向排它锁。

1. 属性锁:
共享锁(S锁):共享 (S) 用于不更改或不更新数据的操作(只读操作),如 SELECT 语句。
如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。

排他锁(X锁):用于数据修改操作(写操作),例如 INSERT、UPDATE 或 DELETE。确保不会同时同一资源进行多重更新。

如果事务T对数据A加上排他锁后,则其他事务不能再对A加任任何类型的封锁。获准排他锁的事务既能读数据,又能修改数据。

共享锁和排他锁最根本的区别在于,加上排他锁后,数据对象只对一个事务可见,而加上共享锁后,数据对所有事务都可见。

2. 粒度锁
表锁是指上锁的时候锁住的是整个表,当下一个事务访问该表的时候,必须等前一个事务释放了锁才能进行对表进行访问;

特点: 粒度大,加锁简单,容易冲突;

行锁是对所有行级别锁的一个统称,比如下面说的记录锁、间隙锁、临键锁都是属于行锁, 行锁是指加锁的时候锁住的是表的某一行或多行记录,多个事务访问同一张表时,只有被锁住的记录不能访问,其他的记录可正常访问;

特点:粒度小,加锁比表锁麻烦,不容易冲突,相比表锁支持的并发要高;

记录锁(Record Lock)
记录锁属于行锁中的一种,记录锁的范围只是表中的某一条记录,记录锁是说事务在加锁后锁住的只是表的某一条记录。

触发条件:精准条件命中,并且命中索引;

记录锁的作用:加了记录锁之后数据可以避免数据在查询的时候被修改的重复读问题,也避免了在修改的事务未提交前被其他事务读取的脏读问题。

间隙锁(Gap Lock)
间隙锁属于行锁中的一种,间隙锁是在事务加锁后其锁住的是表记录的某一个区间,当表的相邻ID之间出现空隙则会形成一个区间,遵循左开右闭原则。

触发条件:范围查询,查询条件必须命中索引、间隙锁只会出现在REPEATABLE_READ(重复读)的事务级别中。

间隙锁作用:防止幻读问题,事务并发的时候,如果没有间隙锁,就会发生如下图的问题,在同一个事务里,A事务的两次查询出的结果会不一样。

临键锁(Next-Key Lock)
临键锁也属于行锁的一种,并且它是INNODB的行锁默认算法,总结来说它就是记录锁和间隙锁的组合,临键锁会把查询出来的记录锁住,同时也会把该范围查询内的所有间隙空间也会锁住,再之它会把相邻的下一个区间也会锁住。

触发条件:范围查询,条件命中了索引。

临键锁的作用:结合记录锁和间隙锁的特性,临键锁避免了在范围查询时出现脏读、重复读、幻读问题。加了临键锁之后,在范围区间内数据不允许被修改和插入。

3. 状态锁
意向锁的解释:当一个事务试图对整个表进行加锁(共享锁或排它锁)之前,首先需要获得对应类型的意向锁(意向共享锁或意向排它锁)

乐观并发控制
除了悲观并发控制机制 - 锁之外,我们其实还有其他的并发控制机制,乐观并发控制(Optimistic Concurrency Control)。乐观并发控制也叫乐观锁,但是它并不是真正的锁,很多人都会误以为乐观锁是一种真正的锁,然而它只是一种并发控制的思想。

乐观锁(Optimistic Locking)认为对同一数据的并发操作不会总发生,属于小概率事件,不用每次都对数据上锁,也就是不采用数据库自身的锁机制,而是通过程序来实现。在程序上,我们可以采用版本号机制或者时间戳机制实现。

乐观锁的版本号机制

在表中设计一个版本字段 version,第一次读的时候,会获取 version 字段的取值。然后对数据进行更新或删除操作时,会执行
UPDATE ... SET version=version+1 WHERE version=version 此时如果已经有事务对这条数据进行了更改,修改就不会成功。

乐观锁的时间戳机制

时间戳和版本号机制一样,也是在更新提交的时候,将当前数据的时间戳和更新之前取得的时间戳进行比较,如果两者一致则更新成功,否则就是版本冲突。

乐观锁适合读操作多的场景,相对来说写的操作比较少。它的优点在于程序实现,不存在死锁问题,不过适用场景也会相对乐观,因为它阻止不了除了程序以外的数据库操作。

悲观锁适合写操作多的场景,因为写的操作具有排它性。采用悲观锁的方式,可以在数据库层面阻止其他事务对该数据的操作权限,防止读 - 写和写 - 写的冲突。

多版本并发控制
当前读 它读取的数据库记录,都是当前最新的版本,会对当前读取的数据进行加锁,防止其他事务修改数据。是悲观锁的一种操作。

快照读 的实现是基于多版本并发控制,即MVCC,既然是多版本,那么快照读读到的数据不一定是当前最新的数据,有可能是之前历史版本的数据。

数据库并发场景

读-读:不存在任何问题,也不需要并发控制
读-写:有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读,幻读,不可重复读
写-写:有线程安全问题,可能会存在更新丢失问题,比如第一类更新丢失,第二类更新丢失
mvcc用来解决读—写冲突的无锁并发控制,就是为事务分配单向增长的时间戳。为每个数据修改保存一个版本,版本与事务时间戳相关联。读操作只读取该事务开始前的数据库快照。

解决问题如下:

并发读-写时:可以做到读操作不阻塞写操作,同时写操作也不会阻塞读操作。
解决脏读、幻读、不可重复读等事务隔离问题,但不能解决上面的写-写 更新丢失问题。
因此有了下面提高并发性能的组合拳:

MVCC + 悲观锁:MVCC解决读写冲突,悲观锁解决写写冲突 例如 MySQL
MVCC + 乐观锁:MVCC解决读写冲突,乐观锁解决写写冲突 例如PostgreSQL
————————————————
版权声明:本文为CSDN博主「Java~ Jeffery」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_41462548/article/details/125154484

标签:事务,记录,数据库,并发,MVCC,操作,机制,数据
From: https://www.cnblogs.com/wlxj/p/17879034.html

相关文章

  • 【数据库概论】第二章 关系型数据库
    2.1关系数据库2.1.1关系关系模型的数据结构十分简单,只包含单一的数据结构——关系。在用户看来,关系模型中数据的逻辑结构是一张扁平的二维表。关系模型的数据结构虽然简单却能表达丰富的语义。在关系模型中,现实世界的实体以及实体之间的联机都是用单一的关系结构类型来表示。......
  • SQL 数据库语句- 创建和管理数据库
    SQLCREATEDATABASE语句SQLCREATEDATABASE语句用于创建一个新的SQL数据库。语法CREATEDATABASE数据库名称;示例以下SQL语句创建了一个名为"testDB"的数据库:CREATEDATABASEtestDB;通过这个简单的语句,你可以成功地创建一个名为"testDB"的数据库。记得在实......
  • 深入探讨Guava的缓存机制
    第1章:引言大家好,我是小黑,今天咱们聊聊GoogleGuava的缓存机制。缓存在现代编程中的作用非常大,它能提高应用性能,减少数据库压力,简直就是性能优化的利器。而Guava提供的缓存功能,不仅强大而且使用起来非常灵活。在咱们深入挖掘之前,先简单说说缓存。缓存,其实就是一种保存数据的手段......
  • 数据库安全性
    数据库的不安全因素:非授权用户对数据库的恶意存取和破坏数据库中重要或敏感的数据被泄露安全环境的脆弱性安全性描述TCSEC/TDI内容:定义了数据库管理系统的设计与实现中需要满足和用以进行安全性级别评估的标准,从4个方面描述安全性级别划分的指标,即安全策略、责任、保证和......
  • 使用 Guava Retry 优雅的实现重试机制
    王有志,一个分享硬核Java技术的互金摸鱼侠加入Java人的提桶跑路群:共同富裕的Java人大家好,我是王有志。今天我会通过一个真实的项目改造案例和大家聊一聊如何优雅的实现Java中常用的的重试机制。业务背景在我们的系统中当客户完成支付后,保单管理系统会通过MQ推送出一条包......
  • 数据库总结复习(sql应用题 二)
    目录前言关系代数关系间运算条件表达式使用案例语法树例子前言本文针对考纲上的30分sql应用题所涉及到的知识进行归纳总结。分为两篇文章,本篇为关系代数相关知识点。关系代数关系间运算关系和关系之间需要用到以下关系运算符:其中,连接从连接条件上分,等值连接,非等值连......
  • 【数据库概论】第一章 数据库概论
    1.1数据库系统概述1.1.1数据库的四个基本概念数据数据库数据库管理系统DBMS数据库系统DBS1.1.2数据库的特点数据结构化数据的共享性高、冗余度低并且易扩充数据独立性高数据由数据库管理系统统一管理和控制1.2数据模型1.1.1数据模型数据模型也是一种模型,他......
  • 垃圾回收机制GC
    垃圾回收机制(GC)(一)什么是垃圾回收机制垃圾回收机制简称GC,是Python解释器自带的一种机制。专门用来回收不可用的变量值所占用的内存空间(在内存中,没有变量名指向的数据都是垃圾数据)(二)垃圾回收机制原理引用计数为主,垃圾回收、分代回收为辅。Python的GC模块主要运用了“引用计......
  • openGauss学习笔记-143 openGauss 数据库运维-例行维护-数据安全维护建议
    openGauss学习笔记-143openGauss数据库运维-例行维护-数据安全维护建议为保证openGauss数据库中的数据安全,避免丢失数据、非法访问数据等事故发生,请仔细阅读以下内容。143.1避免数据被丢失建议用户规划周期性的物理备份,且对备份文件进行可靠的保存。在系统发生严重错误的情况......
  • StackGres 数据库平台工程,使用 Citus + Patroni 创建生产级高可用分布式 PostgreSQL
    系列StackGres,可私有部署的云原生数据库平台工程StackGres 数据库平台工程功能介绍与快速上手StackGres1.6数据库平台工程集群配置管理(K8SPods/PostgreSQL/PgBouncer)StackGres1.6数据库平台工程,集群高可用(Patroni3管理)什么是ShardedCluster(分片集群)Sha......