Mysql的InnoDB存储引擎中的锁机制

embedded/2024/11/17 18:36:25/

       我们将进一步深入到InnoDB存储引擎中的锁机制,包括其内部实现细节、锁的类型、锁的算法、死锁处理以及一些高级特性和最佳实践。

锁的存储结构
  • Lock Struct:InnoDB中的锁结构体Lock_struct包含以下字段:

    • type_mode:锁的类型和模式。
    • trx:持有该锁的事务。
    • rec_lock:指向记录锁的指针。
    • wait:指向等待该锁的下一个锁的指针。
    • next:指向下一个锁的指针。
  • Record Lock:记录锁结构体Rec_lock包含以下字段:

    • heap_no:堆号,标识记录在页面中的位置。
    • index:索引。
    • gap_before 和 gap_after:表示是否锁定记录前后的间隙。
    • next:指向下一个记录锁的指针。
  • Lock Queue:锁队列是一个双向链表,用于管理锁的等待关系。每个锁队列包含一个头节点和一个尾节点,以及指向等待锁的指针。

锁的生命周期
  • 请求锁:当一个事务尝试访问数据时,它会请求相应的锁。
  • 授予锁:如果请求的锁可用,事务立即获得锁;否则,请求被放入锁队列中。
  • 持有锁:事务持有锁直到事务结束(提交或回滚)。
  • 释放锁:事务结束后,锁被释放,其他等待的事务可以获取锁。

锁的算法细节

两阶段锁协议
  • 第一阶段:事务在执行过程中获取所有需要的锁。
  • 第二阶段:事务在提交或回滚时释放所有持有的锁。
  • 优点:保证了事务的原子性和隔离性。
  • 缺点:可能导致较长的锁等待时间,尤其是在长事务中。
锁等待超时
  • 参数innodb_lock_wait_timeout默认值为50秒。
  • 行为:如果一个事务等待锁的时间超过了这个阈值,MySQL会自动回滚该事务。
  • 优化:根据应用的实际情况调整这个参数,以平衡性能和并发性。

死锁检测与解决

死锁检测
  • 锁等待图:InnoDB使用锁等待图来检测死锁。如果图中形成了环,就说明存在死锁。
  • 算法:周期性地检查锁等待图,发现环路即表示死锁。
死锁解决
  • 选择回滚的事务:InnoDB会选择一个事务进行回滚,通常选择代价最小的事务。
  • 代价评估:代价通常是基于事务已经执行的操作量来评估的,如事务已经修改了多少行数据。
  • 回滚过程:回滚事务并释放其持有的所有锁,其他等待的事务可以继续执行。

高级特性

自适应哈希索引(AHI)
  • 作用:AHI是一种内存中的哈希索引,可以显著加快某些查询的速度。
  • 缺点:可能导致锁的竞争,尤其是在高并发环境下。
  • 关闭AHI:可以通过设置innodb_adaptive_hash_index=OFF来关闭AHI,减少锁的竞争。
多版本并发控制(MVCC)
  • 作用:MVCC通过保存数据的历史版本来支持并发读取,从而减少了锁的使用。
  • 实现:每个行记录都有一个隐藏的事务ID字段,用于跟踪创建和删除该记录的事务。读取操作可以根据事务ID看到合适的数据版本。
  • 优点:提高了并发读取的性能。
  • 缺点:增加了存储空间的占用,因为需要保存历史版本。
乐观锁与悲观锁
  • 乐观锁:假设数据一般不会发生并发冲突,因此在读取时不加锁,而在更新时检查是否有其他事务修改了数据。

                 实现:通常通过版本号或时间戳来实现。

                 优点:提高了读取的并发性。

                 缺点:在高并发写入场景下,可能出现大量的更新失败。

  • 悲观锁:假设数据会发生并发冲突,因此在读取时就加锁,以防止其他事务修改数据。

                 实现:通过SELECT ... FOR UPDATESELECT ... LOCK IN SHARE MODE来实现。

                 优点:保证了数据的一致性。

                 缺点:降低了并发性,特别是在高并发读写场景下。

性能优化

索引优化
  • 选择合适的索引:确保查询使用有效的索引,以减少锁定的范围。
  • 覆盖索引:尽量使用覆盖索引,这样查询可以直接从索引中获取所需数据,而不需要访问表数据。
  • 索引维护:定期重建索引,以保持索引的高效性。
事务优化
  • 减少事务大小:尽量保持事务简短,减少锁的持有时间。
  • 批量操作:尽量批量处理数据,减少锁的竞争。
  • 锁等待超时:合理设置innodb_lock_wait_timeout,避免长时间等待锁。
锁模式的选择
  • 共享锁 vs 排他锁:根据实际需求选择适当的锁模式。例如,只读操作可以选择共享锁,而写操作则需要排他锁。
监控与诊断
  • 使用SHOW ENGINE INNODB STATUS:查看当前的锁信息和潜在的性能瓶颈。
  • 性能监控工具:如Percona Toolkit、pt-deadlock-logger等,可以帮助你监控和分析锁的情况。

实际案例

        假设有一个在线商城系统,其中有一个products表,包含id(主键)、nameprice等字段。在促销活动中,需要对特定商品的价格进行更新。以下是可能的操作:

START TRANSACTION;
-- 更新产品ID为100的商品价格
UPDATE products SET price = 99.80 WHERE id = 100;
COMMIT;

       在这个例子中,InnoDB会对id = 100的行加排他锁(X锁),防止其他事务在更新过程中修改该行。如果查询条件没有命中索引,InnoDB可能会对整个表加锁,导致严重的性能问题。因此,确保查询条件能够命中索引是非常重要的。

具体示例:锁的获取与释放

示例1:简单的更新操作
START TRANSACTION;
UPDATE products SET price = 79.60 WHERE id = 100;
COMMIT;
  • 步骤1:事务开始。
  • 步骤2:事务请求对id = 100的行加排他锁(X锁)。
  • 步骤3:如果锁可用,事务立即获得锁;否则,请求被放入锁队列中等待。
  • 步骤4:事务执行更新操作。
  • 步骤5:事务提交,释放持有的锁。
示例2:复杂的查询操作
START TRANSACTION;
SELECT * FROM products WHERE price > 50 FOR UPDATE;
COMMIT;
  • 步骤1:事务开始。
  • 步骤2:事务请求对满足price > 50条件的所有行加排他锁(X锁)。
  • 步骤3:如果锁可用,事务立即获得锁;否则,请求被放入锁队列中等待。
  • 步骤4:事务执行查询操作。
  • 步骤5:事务提交,释放持有的锁。

总结

       通过以上详细的解释,你应该对InnoDB存储引擎中的锁机制有了更深入的理解。锁机制是保证数据库并发性和数据一致性的关键部分。合理的设计和优化锁策略,可以大大提高数据库系统的性能和稳定性。


http://www.ppmy.cn/embedded/138310.html

相关文章

【Python模拟websocket登陆-拆包封包】

Python模拟websocket登陆-拆包封包 解析一个网站获取wss原始数据拆包wss数据封包wss数据发送接收websocket的常驻后台脚本总结 解析一个网站 这里所用的网站是我一个内测的网站,主要手段是chrome devtools,用得很多,但我玩的不深&#xff0c…

数学分组求偶数和

问题描述 小M面对一组从 1 到 9 的数字,这些数字被分成多个小组,并从每个小组中选择一个数字组成一个新的数。目标是使得这个新数的各位数字之和为偶数。任务是计算出有多少种不同的分组和选择方法可以达到这一目标。 numbers: 一个由多个整数字符串组…

C++(Qt)软件调试---内存泄漏分析工具MTuner (25)

C(Qt)软件调试—内存泄漏分析工具MTuner (25) 文章目录 C(Qt)软件调试---内存泄漏分析工具MTuner (25)[toc]1、概述🐜2、下载MTuner🪲3、使用MTuner分析qt程序内存泄漏🦧4、相关地址&#x1f41…

在移动硬盘中创建vue项目 报错

如图所示,在U盘或者移动硬盘当中 创建vue项目,报错 如图所示, 这个问题与 Git 的安全设置有关,尤其是在跨用户或跨文件系统的环境下(例如,移动硬盘或不同账户)。Git 检测到当前项目的文件夹 的…

Flutter开发之flutter_local_notifications

flutter_local_notifications 消息通知 flutter_local_notifications地址 flutter_local_notifications: ^18.0.1class NotificationHelper {//工厂模式调用该类时,默认调用此方法,将实例对象返回出去static NotificationHelper? _instance null;sta…

2024智能机器人与自动控制国际学术会议 (IRAC 2024)

主办,承办,支持单位 会议官网 www.icirac.org 大会时间:2024年11月29-12月1日 大会简介 2024智能机器人与自动控制国际学术会议 (IRAC 2024)由华南理工大学主办,会议将于2024年11月29日-12月1日在中国广…

php回调函数(匿名)的使用

在 PHP 中&#xff0c;回调函数&#xff08;或匿名函数&#xff09;可以通过参数传递值&#xff0c;通常是在调用该回调时提供的。回调函数可以接收传入的值&#xff0c;并在其内部使用这些值。 <?php/*** php回调函数&#xff08;匿名&#xff09;的使用* 通过参数传递值…

fastadmin多个表crud连表操作步骤

1、crud命令 php think crud -t xq_user_credential -u 1 -c credential -i voucher_type,nickname,user_id,voucher_url,status,time --forcetrue2、修改控制器controller文件 <?phpnamespace app\admin\controller;use app\common\controller\Backend;/*** 凭证信息…