关于InnoDB行锁和4种锁是怎么实现的?

InnoDB 的行锁实现主要基于索引,并通过多种类型的锁来确保数据的一致性和并发控制。以下是InnoDB行锁实现的几个关键点:

  1. 记录锁(Record Locks):这种锁直接锁定某行记录的索引记录。它通常用于唯一索引或主键索引上,当使用精确匹配的查询条件(如id = 1)时,会使用记录锁。如果查询条件不使用索引或使用非精确匹配条件,则可能退化为临键锁 。

  2. 间隙锁(Gap Locks):间隙锁锁定一段范围内的索引记录,但不包括记录本身。这种锁基于非唯一索引,并且是Next-Key Locking算法的一部分。间隙锁可以阻止其他事务在锁定的间隙中插入新的记录 。

  3. 临键锁(Next-Key Locks):这是InnoDB中的一种特殊锁,结合了记录锁和间隙锁的特性。每个数据行上的非唯一索引列上都可能存在临键锁,它锁定一个左开右闭的索引区间,从而解决幻读问题 。

  4. 意向锁(Intention Locks):InnoDB使用意向锁来支持行级锁和表级锁的共存。意向锁包括意向共享锁(IS)和意向排他锁(IX),它们在事务需要在更高层次上加锁时自动添加,以便与行级锁兼容 。

下面 V 哥来跟据业务场景,举例说明4种行锁的使用。

1. 记录锁(Record Locks)

记录锁(Record Locks)是InnoDB中用于锁定特定数据行的锁。以下是一些具体的业务场景和示例,说明记录锁的使用方法和效果:

场景一:更新操作

当需要更新某行数据时,通常会使用记录锁来确保在更新过程中数据不会被其他事务修改。

示例
假设有一个订单表orders,其中包含订单ID、订单状态等字段。当一个订单的状态需要从“待发货”更新为“已发货”时,可以使用以下SQL语句:

UPDATE orders SET status = '已发货' WHERE order_id = 1;

在这个例子中,InnoDB会在order_id索引上加一个记录锁,锁定订单ID为1的行。其他事务在该行数据被解锁之前,不能对其进行修改。

场景二:查询并锁定

在某些情况下,需要先查询某行数据,然后对其进行操作。这时可以使用SELECT ... FOR UPDATE语句来锁定查询结果中的行。

示例
假设需要查询某个用户的详细信息,并在查询后更新其资料。可以使用以下语句:

SELECT * FROM users WHERE user_id = 1 FOR UPDATE;

这条语句不仅会返回用户ID为1的记录,还会在user_id索引上加一个记录锁。其他事务在该行数据被解锁之前,不能对其进行修改或查询。

场景三:防止数据被其他事务修改

在某些业务逻辑中,可能需要确保某行数据在一段时间内不会被其他事务修改。

示例
假设有一个库存表inventory,需要确保在计算库存的过程中数据不会被其他事务修改。

SELECT * FROM inventory WHERE product_id = 100 FOR UPDATE;

这条语句会锁定产品ID为100的库存记录,直到当前事务结束。在此期间,其他事务不能修改该记录。

场景四:避免数据重复插入

在插入数据时,如果需要避免插入重复的数据,可以使用记录锁来确保唯一性。

示例
假设有一个用户表users,需要插入一个新的用户记录,但要确保用户名是唯一的。

INSERT INTO users (username, email) VALUES ('newuser', 'newuser@example.com') ON DUPLICATE KEY UPDATE email = 'newuser@example.com';

如果username字段是唯一索引,这条语句会首先尝试插入新记录。如果用户名已存在,InnoDB会在username索引上加一个记录锁,并更新现有记录的电子邮件地址。

场景五:事务中的一致性读取

在事务中,如果需要确保读取的数据在事务执行期间不被其他事务修改,可以使用记录锁来实现。

示例
假设在一个事务中需要读取并处理某个订单的所有相关信息。

START TRANSACTION;SELECT * FROM orders WHERE order_id = 10 FOR UPDATE;-- 执行一些业务逻辑处理COMMIT;

在这个事务中,SELECT ... FOR UPDATE语句会锁定订单ID为10的记录,确保在事务执行期间其他事务不能修改该记录。

通过这些示例,可以看到记录锁在确保数据一致性和防止数据被并发事务修改方面的重要性。

2. 间隙锁(Gap Locks)

间隙锁(Gap Locks)在InnoDB中用于锁定一个范围内的记录,但不包括记录本身。这种锁主要用于防止其他事务在这个范围内插入新的记录,从而维护数据的一致性和顺序。以下是一些具体的业务场景和示例,说明间隙锁的使用方法和效果:

场景一:防止数据插入

在某些业务逻辑中,可能需要确保某个范围内的数据不会被其他事务插入,以维护数据的完整性。

示例
假设有一个员工表employees,包含员工ID和部门ID。如果需要防止在某个部门ID范围内插入新的员工记录,可以使用以下SQL语句:

SELECT * FROM employees WHERE department_id BETWEEN 10 AND 20 FOR UPDATE;

这条语句会锁定部门ID在10到20之间的所有记录,但不包括这些记录本身。其他事务在该范围内不能插入新的员工记录,直到当前事务结束。

场景二:范围查询并锁定

在进行范围查询时,如果需要确保查询结果中的记录不会被其他事务修改,可以使用间隙锁。

示例
假设需要查询某个日期范围内的所有订单,并锁定这些订单记录。

SELECT * FROM orders WHERE order_date BETWEEN '2024-01-01' AND '2024-01-31' FOR UPDATE;

这条语句会锁定所有订单日期在2024年1月1日到1月31日之间的订单记录。其他事务在当前事务结束之前,不能修改这些订单记录。

场景三:避免数据重复

在插入数据时,如果需要避免在某个范围内插入重复的数据,可以使用间隙锁来确保唯一性。

示例
假设有一个产品表products,需要确保在某个价格范围内不会插入重复的产品。

SELECT * FROM products WHERE price BETWEEN 100 AND 200 FOR UPDATE;

这条语句会锁定价格在100到200之间的所有产品记录,但不包括这些记录本身。其他事务在当前事务结束之前,不能在这个价格范围内插入新的产品记录。

场景四:维护数据顺序

在某些业务逻辑中,可能需要确保数据的插入顺序,间隙锁可以用于维护这种顺序。

示例
假设有一个任务表tasks,需要确保任务的插入顺序按照任务的优先级进行。

SELECT * FROM tasks WHERE priority BETWEEN 1 AND 5 FOR UPDATE;

这条语句会锁定优先级在1到5之间的所有任务记录,但不包括这些记录本身。其他事务在当前事务结束之前,不能在这个优先级范围内插入新的任务记录。

场景五:防止数据覆盖

在某些情况下,可能需要防止在某个范围内的数据被其他事务覆盖。

示例
假设有一个库存表inventory,需要确保在某个库存量范围内的数据不会被其他事务覆盖。

SELECT * FROM inventory WHERE stock_level BETWEEN 50 AND 100 FOR UPDATE;

这条语句会锁定库存量在50到100之间的所有库存记录,但不包括这些记录本身。其他事务在当前事务结束之前,不能在这个库存量范围内插入或修改库存记录。

通过这些示例,可以看到间隙锁在防止数据被并发事务插入和维护数据一致性方面的重要性。

3. 临键锁(Next-Key Locks)

临键锁(Next-Key Locks)是InnoDB中一种特殊的锁,它结合了记录锁和间隙锁的特点,用于锁定一个记录及其后继记录之间的“间隙”。这种锁主要用于解决幻读问题,确保在可重复读(Repeatable Read)隔离级别下,事务可以看到一致的快照视图。

以下是一些具体的业务场景和示例,说明临键锁的使用方法和效果:

场景一:防止幻读

在可重复读隔离级别下,如果一个事务需要多次读取同一数据集,临键锁可以确保在事务执行期间,其他事务不能在这些数据之间插入新的记录。

示例
假设有一个订单表orders,包含订单ID和订单状态。一个事务需要多次检查某个订单的状态,确保在处理期间订单状态没有被其他事务修改。

START TRANSACTION;
SELECT * FROM orders WHERE order_id = 100 FOR UPDATE;
-- 检查订单状态
-- 执行一些业务逻辑
SELECT * FROM orders WHERE order_id = 100 FOR UPDATE;
COMMIT;

在这个例子中,第一次SELECT ... FOR UPDATE会锁定订单ID为100的记录,同时也会锁定该记录后面的间隙,防止其他事务在这个间隙中插入新的订单记录。

场景二:范围查询并锁定

在进行范围查询时,如果需要确保查询结果中的记录不会被其他事务插入或修改,可以使用临键锁。

示例
假设需要查询某个价格范围内的所有产品,并锁定这些产品记录。

SELECT * FROM products WHERE price BETWEEN 100 AND 200 FOR UPDATE;

这条语句会锁定价格在100到200之间的所有产品记录,同时也会锁定这些记录后面的间隙。其他事务在当前事务结束之前,不能在这个价格范围内插入新的产品记录,也不能修改这些记录。

场景三:维护数据顺序

在某些业务逻辑中,可能需要确保数据的插入顺序,临键锁可以用于维护这种顺序。

示例
假设有一个任务表tasks,需要确保任务的插入顺序按照任务的优先级进行。

SELECT * FROM tasks WHERE priority BETWEEN 1 AND 5 FOR UPDATE;

这条语句会锁定优先级在1到5之间的所有任务记录,同时也会锁定这些记录后面的间隙。其他事务在当前事务结束之前,不能在这个优先级范围内插入新的任务记录。

场景四:防止数据覆盖

在某些情况下,可能需要防止在某个范围内的数据被其他事务覆盖。

示例
假设有一个库存表inventory,需要确保在某个库存量范围内的数据不会被其他事务覆盖。

SELECT * FROM inventory WHERE stock_level BETWEEN 50 AND 100 FOR UPDATE;

这条语句会锁定库存量在50到100之间的所有库存记录,同时也会锁定这些记录后面的间隙。其他事务在当前事务结束之前,不能在这个库存量范围内插入新的库存记录,也不能修改这些记录。

场景五:数据一致性检查

在某些业务逻辑中,可能需要在事务中多次检查数据的一致性,临键锁可以确保在检查期间数据不会被其他事务修改。

示例
假设有一个员工表employees,需要在事务中多次检查某个员工的薪资是否符合预期。

START TRANSACTION;
SELECT * FROM employees WHERE employee_id = 1 FOR UPDATE;
-- 检查薪资
-- 执行一些业务逻辑
SELECT * FROM employees WHERE employee_id = 1 FOR UPDATE;
COMMIT;

在这个例子中,SELECT ... FOR UPDATE会锁定员工ID为1的记录,同时也会锁定该记录后面的间隙,确保在事务执行期间其他事务不能在这个间隙中插入新的员工记录或修改该员工的薪资。

通过这些示例,可以看到临键锁在防止幻读、维护数据一致性和顺序方面的重要性。

4. 意向锁(Intention Locks)

意向锁(Intention Locks)是InnoDB存储引擎中的一种内部使用的锁,用于表示事务将要请求的锁类型,并帮助事务在不同级别的锁(行锁和表锁)之间实现兼容性。意向锁主要有以下两种类型:

  1. 意向共享锁(Intention Shared Lock,IS):事务在请求多个行的共享锁之前,首先在表级别加上意向共享锁。
  2. 意向排他锁(Intention Exclusive Lock,IX):事务在请求多个行的排他锁之前,首先在表级别加上意向排他锁。

下面是业务场景和示例:

场景一:多行数据的更新

当需要更新表中的多行数据时,事务会在表级别加上意向排他锁,以表明它打算在表中放置排他锁。

示例
假设有一个在线购物平台的订单表orders,需要批量更新多个订单的状态为“已发货”。

START TRANSACTION;UPDATE orders SET status = 'Shipped' WHERE order_id IN (101, 102, 103);COMMIT;

在这个事务中,InnoDB会在orders表上自动加上意向排他锁(IX),然后在每条选定的订单记录上加上排他锁(X)。这表明事务打算修改这些行,并且其他事务不能同时修改这些行或在表上加上共享锁。

场景二:多行数据的读取

如果一个查询需要读取多行数据,并且事务需要确保这些数据在读取期间不被修改,事务会在表级别加上意向共享锁。

示例
假设需要为报表生成读取特定条件的订单数据,以确保在生成报表期间这些订单数据不被修改。

START TRANSACTION;SELECT * FROM orders WHERE customer_id = 100 FOR UPDATE;COMMIT;

在这个事务中,InnoDB会在orders表上自动加上意向排他锁(IX),然后在满足条件的每一行上加上排他锁(X)。这确保了在事务期间,其他事务不能修改这些订单记录。

场景三:避免死锁

在复杂的业务逻辑中,多个事务可能需要在不同的表或同一表的不同行上请求锁。意向锁有助于避免死锁,因为它允许事务在请求行锁之前表明其锁意图。

示例
假设有两个事务,事务A需要更新orders表和customers表,事务B也需要更新这两个表,但顺序相反。

事务A:

START TRANSACTION;UPDATE orders SET ... WHERE order_id = 101;
UPDATE customers SET ... WHERE customer_id = 100;COMMIT;

事务B:

START TRANSACTION;UPDATE customers SET ... WHERE customer_id = 100;
UPDATE orders SET ... WHERE order_id = 101;COMMIT;

即使两个事务请求锁的顺序不同,意向锁的存在可以确保它们在请求行锁之前在表级别请求相应的意向锁,从而降低死锁的风险。

场景四:表结构变更时的兼容性

当数据库管理员需要对表结构进行变更,如添加索引,而表中已有行锁时,意向锁提供了一种机制来确保结构变更不会与现有的行级锁冲突。

示例
数据库管理员需要为orders表添加一个新索引,但表中已有多个行被锁。

ALTER TABLE orders ADD INDEX (new_column);

在这个操作中,InnoDB会在表级别检查意向锁,以确保没有其他事务正在修改表中的数据,从而安全地进行索引的添加。

意向锁是InnoDB内部自动处理的,不需要用户手动请求。它们在事务需要在多行上请求共享锁或排他锁时,提供了一种高效的协调机制,以确保数据库的并发控制和数据一致性。

5. 最后

快照读取和读取冲突检测:InnoDB通过快照读取确保事务读取到的数据一致性,并通过读取冲突检测来处理并发事务中的冲突,确保数据的正确性和一致性 。

锁的兼容性:InnoDB中的锁有一套兼容性规则,共享锁(S)和排他锁(X)可以共存,但排他锁会阻塞其他事务对同一资源的访问。意向锁是InnoDB自动添加的,不需要用户干预 。

行锁的实现方式:InnoDB行锁是通过给索引上的索引项加锁实现的。如果查询不通过索引条件,InnoDB将使用表锁而不是行锁,这可能会影响并发性能 。

锁的优化:合理使用索引,减少锁的持有时间,避免死锁等策略可以帮助优化InnoDB行锁的性能 。

总的来说,InnoDB的行锁机制通过索引来实现对数据行的精确控制,并通过多种锁类型和兼容性规则来处理并发事务中的冲突。开发者需要注意合理使用索引和优化事务处理,以提高数据库的并发性能和稳定性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/48290.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu20.04安装终端终结者并设置为默认终端

1、安装 terminator sudo apt-get install terminator 2、Ctrl Alt T 试一下打开什么终端,我的默认启动的是terminator;如果想换换默认的终端,还需以下一步 3、安装dconf-tools,这个是设置默认终端的必须 sudo apt-get install dconf-tools…

数据结构初阶-单链表

链表的结构非常多样,以下情况组合起来就有8种(2 x 2 x 2)链表结构: 而我们主要要熟悉的单链表与双向链表的全称分别为:不带头单向不循环链表,带头双向循环链表,当我们对这两种链表熟悉后&#x…

重生之我们在ES顶端相遇第5章-常用字段类型

思维导图 前置 在第4章,我们提到了 keyword(一笔带过)。在本章,我们将介绍 ES 的字段类型。全面的带大家了解 ES 各个字段类型的使用场景。 字段类型 ES 支持以下字段类型(仅介绍开发中常用,更多内容请自…

大模型之RAG-关键字检索的认识与实战(混合检索进阶储备)

前言 按照我们之前的分享(大模型应用RAG系列3-1从0搭建一个RAG:做好文档切分): RAG系统搭建的基本流程 准备对应的垂域资料文档的读取解析,进行文档切分将分割好的文本灌入检索引擎(向量数据库&#xff…

AI App Store-AI用户评价-多维度打分对比pk-AI社区

C端用户、创作者、AI达人们在选择众多国内外AI厂商的服务时候往往感到一头雾水,那么多功能接近的AI应用(智能对话类、文档总结类、文生图、AI搜索引擎) 究竟在不同用户需求场景下表现怎么样。大部分人如果有需求都会所有平台都尝试一遍,比如一个博主生成…

Linux内网离线用rsync和inotify-tools实现文件夹文件单向同步和双向同步

lsyncd实现方式可参考:https://www.jianshu.com/p/c075ccf89516 安装文件下载:相关文件下载 rsync默认都有,所以没有提供。 服务端和客户端均操作 服务端:双向同步其实都是服务端,只是单向同步时稍有区别 客户端&am…

C++自定义字典树结构

代码 #include <iostream> using namespace std;class TrieNode { public:char data;TrieNode* children[26];bool isTerminal;TrieNode(char ch){data ch;for (int i 0; i < 26; i){children[i] NULL;}isTerminal false;} }; class Trie { public:TrieNode* ro…

Android、Java反编译工具JADX

目录 介绍 主要特点: jadx-gui特性: 下载地址 使用 介绍 jadx - Dex to Java反编译器 用于从Android Dex和Apk文件生成Java源代码的命令行和GUI工具 请注意,在大多数情况下,jadx不能100%反编译所有的代码,所以会出现错误。 有关变通方法,请参阅故障排除指南。 目前…

返回倒数第 k 个节点 - 力扣(LeetCode)

面试题 02.02. 返回倒数第 k 个节点 - 力扣&#xff08;LeetCode&#xff09; /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/int kthToLast(struct ListNode* head, int k) {struct ListNode* fastnode head…

git面面观,面试题,常见问题

1. 简述什么是Git &#xff1f; Git是一款分布式源代码管理工具(版本控制工具) 。 Git得其数据更像是一系列微型文件系统的快照。使用Git&#xff0c;每次提交或保存项目状态时&#xff0c;Git基本上都会记录当时所有文件的外观&#xff0c;并存储对该快照的引用。为了提高效…

Prompt工程:与AI聊天机器人更好地交流

Prompt工程:与AI聊天机器人更好地交流 1. 清楚地说明你想要什么2. 告诉AI它现在是谁3. 一步一步来4. 给AI一些例子5. 让AI检查自己的回答6. 把AI当作你的小助手7. 让AI帮你想主意8. 让AI告诉你它需要知道什么9. 教AI一步一步思考结语 大家好!今天我们来聊聊如何跟AI聊天机器人更…

互三群危害?如何才能正确上热榜。

前言 攀登热门榜单之巅&#xff0c;历来是才华与智慧较量的舞台&#xff0c;策略与努力的结晶。然而&#xff0c;在这片看似光鲜的网络世界里&#xff0c;也潜藏着不为人知的暗流——“互三群”的歪风邪气。揭露其真面目&#xff0c;以正网络风气&#xff0c;是每一位网络创作…

基于区块链技术的中药饮片代煎配送服务与监管平台

业务背景 近年来&#xff0c;随着公众对中医药青睐有加&#xff0c;中药代煎服务作为中医药现代化的重要一环&#xff0c;在全国各地蓬勃兴起。鉴于传统煎煮方式的繁琐耗时&#xff0c;医疗机构纷纷转向与第三方中药饮片企业合作&#xff0c;采用集中代煎模式。这些第三方煎药中…

Proactor模型

文章目录 概述1. 异步I/O操作2. 事件通知3. 事件处理函数4. 事件循环5. 多线程支持6. 非阻塞I/O7. 可扩展性8. 错误处理9. 资源管理10. 编程复杂性11. 应用场景流程图 结论 概述 Proactor模型是一种基于异步I/O操作的事件驱动编程模型&#xff0c;主要用于处理并发的I/O事件&a…

冒泡排序(数组作为函数参数)

什么是冒泡排序&#xff1f; 冒泡排序&#xff08;Bubble Sort&#xff09;也是一种简单直观的排序算法。它重复地走访过要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换&#xff0c;…

【Unity】RPG2D龙城纷争(十五)特殊加成型要诀

更新日期:2024年7月22日。 项目源码:第五章发布(正式开始游戏逻辑的章节) 索引 简介一、特殊加成型要诀基类二、扩充要诀数据集三、移动寻路时,应用特殊加成效果四、攻击寻路时,应用特殊加成效果五、攻击别人时,应用特殊加成效果六、被别人攻击时,应用特殊加成效果七、…

docker--容器数据进行持久化存储的三种方式

文章目录 为什么Docker容器需要使用持久化存储1.什么是Docker容器&#xff1f;2.什么是持久化存储&#xff1f;3.为什么Docker容器需要持久化存储&#xff1f;4.Docker如何实现持久化存储&#xff1f;(1)、Docker卷(Volumes)简介适用环境:使用场景:使用案例: (2)、绑定挂载&…

pycharm+pytorch2.3.1安装

成功运行 Anaconda简介 Anaconda 就是可以便捷获取包且对包能够进行管理&#xff0c;同时对环境可以统一管理的发行版本。Anaconda包含了conda、Python在内的超过180个科学包及其依赖项。 Anaconda安装 去官网地址下载 Download Anaconda Distribution | Anaconda​www.ana…

PHP常量

PHP 常量是在脚本执行期间其值不会改变的量。它们通常用于存储不经常改变的值&#xff0c;如配置选项、数据库连接信息等。在 PHP 中&#xff0c;常量与变量不同&#xff0c;一旦定义就不能被重新定义或取消定义&#xff08;直到脚本执行结束&#xff09;。下面是关于 PHP 常量…

SpringBoot启动原理详解

透彻理解SpringBoot启动原理&#xff08;一&#xff09; 一张Spring启动顺序图我们对Spring启动原理有多少理解呢一起看一下Spring有那些扩展点和启动过程有关通过打印日志学习Spring的执行顺序实例化和初始化的区别Spring重要扩展点的启动顺序1.BeanFactoryPostProcessor2.实例…