MySQL中的锁详解

news/2024/12/22 23:32:38/

1.概念

锁是计算机协调多个进程或者线程并发访问某一资源的机制。那么如何保证数据并发访问的一致性、有效性是数据库必须解决的一个问题,锁的冲突也是影响数据库并发访问性能的一个重要因素,所以数据库中锁的应用极为重要,其复杂度也更高。

锁的分类,以锁的颗粒度为三类:

  1. 全局锁:锁定数据库中的所有表。
  2. 表级锁:每次操作锁住整张表。
  3. 行级锁:每次操作都锁到对应行的数据。

接下来就分别对这几种锁做一个解释。

 数据库锁是数据库管理系统用来管理对数据库中数据的并发访问的一种机制。锁的存在主要是为了保证数据的完整性和一致性,以及支持事务的原子性。以下是全局锁、表级锁和行级锁的详细解释:

1.  全局锁(Global Lock):

•  全局锁是一种锁定数据库中所有表的锁。当数据库处于只读模式时,通常使用全局锁。
•  在这种模式下,没有写操作被允许,只能执行读操作。这可以用于数据库的备份或维护期间,以防止数据被修改。
•  全局锁的范围是最广的,它锁定了整个数据库实例,所有试图进行写操作的事务都会被阻塞。

-- 全局锁,整个数据库处于只读状态,其他操作均阻塞
FLUSH TABLES WITH READ LOCK-- 释放全局锁
UNLOCK TABLES

2.  表级锁(Table-Level Lock):

•  表级锁是锁定数据库中特定表的锁。当一个事务对表进行写操作(如 INSERT、UPDATE、DELETE)时,通常会请求表级锁。
•  表级锁会阻止其他事务对同一张表进行写操作,但仍然允许其他事务对这张表进行读操作,这取决于锁的类型(共享锁或排他锁)。
•  表级锁的粒度比全局锁小,它只锁定涉及的特定表,其他表可以被并发访问。 

3.  行级锁(Row-Level Lock):

•  行级锁是锁定数据库表中特定行记录的锁。这种锁的粒度最细,只锁定事务操作影响到的具体行。
•  行级锁通常在执行精确的数据操作时使用,如 UPDATE 某个具体的行或 DELETE 某个具体的行。

共享锁和排他锁 

  • 共享锁(S Lock):其他事务可读,但不可写
  • 排他锁(X Lock):其他事务不能读取也不能写

 这两种行锁之间的兼容性如下:7bb394b92dc24592979e8d1fe676bdd5.png

 共享锁和共享锁可以兼容,排他锁和其它锁都不兼容。例如,事务 A 获取了一行数据的共享锁,事务 B 可以立即获得该数据行的共享锁,也就是锁兼容;但是此时事务 B 如果想获得该数据行的排他锁,则必须等待事务 A 释数据行上的共享锁,此种情况存在锁冲突。

默认情况下,数据库中的锁都可以自动获取;但是也可以手动为数据进行加锁。我们来看一个示例,首先创建一个表:

create table t(id int auto_increment primary key,c1 int,c2 int,c3 int
);
create unique index idx_t_c1 on t(c1);
create index idx_t_c2 on t(c2);insert into t(c1,c2,c3) values (1,1,1),(2,3,4),(3,6,9);

其中,id 是主键;c1 上创建了一个唯一索引;c2 上创建了一个非唯一索引;c3 上没有索引。

接下来的示例都使用 MySQL 默认的隔离级别 Repeatable Read,除非另有说明。

然后创建两个数据库连接 T1 和 T2,先在 T1 中锁定一行数据:

-- T1
mysql> begin;
Query OK, 0 rows affected (0.00 sec)mysql> select * from t where id = 1 for share;
+----+------+------+------+
| id | c1   | c2   | c3   |
+----+------+------+------+
|  1 |    1 |    1 |    1 |
+----+------+------+------+
1 row in set (0.00 sec)

我们在事务中使用select ... for share语句获得了数据行 id = 1 上的共享锁;对于 MySQL 8.0 之前的版本,可以使用select ... lock in share mode命令。

由于 InnoDB 中的自动提交 autocommit 默认设置为 ON,我们必须在事务中为数据行加锁;或者将 autocommit 设置为 OFF。

然后在 T2 中执行以下语句: 

-- T2
mysql> select * from t where id = 1 for share;
+----+------+------+------+
| id | c1   | c2   | c3   |
+----+------+------+------+
|  1 |    1 |    1 |    1 |
+----+------+------+------+
1 row in set (0.00 sec)

结果显示,在 T2 中成功获取改行数据上的共享锁。然后尝试获取排他锁:

-- T2
mysql> select * from t where id = 1 for update;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

使用select ... for update命令获取排他锁,此时该命令会一直处于等待状态并且最终超时。也就是说,共享锁和排他锁不兼容。

最后,在 T1 中提交或者回滚事务:

-- T1
mysql> commit;

 

 

 


http://www.ppmy.cn/news/1516559.html

相关文章

Kafka的生产者和消费者机制

目录 1.基础的客户端 1.1消息发送者的主流程 1.2消息消费者主流程 2.客户端工作机制 2.1消费者分组消费机制 2.2生产者拦截器机制 2.3消息序列化机制 2.4消息分区路由机制 2.5生产者消息缓存机制 2.6发送应答机制 2.7生产者消息幂等性 (1)生产者消息幂等性介绍 (2…

sql报错之 : The user specified as a definer (‘xxx‘@‘%‘) does not exiet

报错详情 : 其中这个xxx是在定义触发器的时候 的 定义者 , 触发器详情代码 : ## 创建新增评论数据触发器,一旦新增评论则对应视频的评论量加一 CREATE DEFINERxxx% TRIGGER increment_comment_count AFTER INSERT ON comment FOR EACH ROW BEGINUPDAT…

mac在终端中使用vscode打开文件或者文件夹

在Mac上使用Visual Studio Code(VSCode)打开指定文件夹,你可以通过以下步骤操作: 1.创建软连接 1.找到VSCode的安装位置。在Finder中,导航到/Applications/Visual Studio Code.app 2.进入VSCode的内容文件夹&#x…

小琳AI课堂:使用ChatGPT API搭建系统(二)

🎉 Python与ChatGPT API的奇妙之旅 🎉 大家好,欢迎回到小琳AI课堂!今天我们要探索的是如何在“使用ChatGPT API搭建系统”课程中,用Python代码与ChatGPT API进行有趣的互动。准备好了吗?让我们开始吧&#…

Leetcode每日刷题之1658.将x减到0的最小操作数(C++)

1.题目解析 本题的要求是给出一个正整数数组与一个x,要求只从数组两端取数据后x减去取出的数据,求出将x减为0的最小操作数,即找出数组两端的数字保证其和为x并且要求取出的数字个数最少,如果没有符合要求的数字则返回-1 题目来源&…

使用redis模拟cookie-session,例子:实现验证码功能

目录 在前后端分离架构中不建议使用cookie-session机制实现端状态识别 所以我们可以使用redis来模拟session-cookie机制 下面我们通过实现验证码的功能来举例 第一步:了解前端要我们返回的数据变量名字,变量类型 1.封装code,data成一个result类&…

Android 架构模式之 MVVM

Android 架构 Android 架构模式之 MVCAndroid 架构模式之 MVPAndroid 架构模式之 MVVM 目录 Android 架构架构设计的目的对 MVVM 的理解代码ModelViewViewModel Android 中 MVVM 的问题试吃个小李子BeanModelViewViewModel效果展示 大家好! 作为 Android 程序猿&a…

卡片写作只是基础

卡片写作法,降低了写作门槛,让很多人开始喜欢写作,积累了不少。 接下来问题来了,卡片写作的内容,将来怎么输出啊,卡片和文章什么关系?如何写成文章? 这个问题,我最初以…