MySQL 深潜 - MDL 锁的实现与获取机制
发布网友
发布时间:2小时前
我来回答
共1个回答
热心网友
时间:2024-12-02 12:55
为了满足数据库在并发请求下的事务隔离性和一致性要求,同时针对 MySQL 插件式多种存储引擎都能发挥作用,MySQL 在 Server 层实现了 Metadata Locking(MDL)机制。MDL 机制采用键值对方式描述对象,并通过灵活定制锁的对象、类型以及优先级,以及动态调整锁类型的兼容性,极大方便了数据库对各种查询请求进行合理的并发控制。
MDL 系统包含多个关键数据结构,如 MDL_key、enum_mdl_type、MDL_request、MDL_lock、MDL_ticket 和 MDL_context。MDL_key 通过字符串形式描述锁的对象,包含 namespace、类型名称和对象名称。enum_mdl_type 则定义了不同类型的锁,如范围锁和对象锁,用于控制不同查询语句的并发访问。
MDL 获取过程首先在 parse 阶段由 LEX 和 YACC 根据语句类型初始化 MDL 锁请求。然后,通过 open_tables_for_query 函数将所有需要访问的表打开,并获取 MDL 锁。在 MDL_context::try_acquire_lock_impl 函数中,系统首先检查线程已持有的相同对象的 MDL_ticket,优先使用 fast path 方式获取锁。对于 obtrusive 类型的 MDL 请求,需通过 slow path 方式遍历 m_granted 链表和其他 bitmap 来判断是否存在锁冲突。锁获取失败时,线程将加入锁等待队列,直到其他线程释放锁。
死锁检测在锁等待之前进行,确保线程不会陷入等待循环。通过 MDL_wait_for_subgraph 和 Deadlock_detection_visitor 实现死锁检测,首先广度优先搜索,然后深度优先搜索,确定是否存在死锁并选择受害者线程释放锁。监控 MDL 锁的获取情况可通过 MySQL performance_schema 实现,查看 performance_schema.metadata_locks 表。
PolarDB 在 MDL 上的优化引入了分区级别的 MDL 锁,使得 DML 和 DDL 获取的锁粒度降低到分区级,提高了并发度,实现了“在线”分区维护功能。用户可以自由进行分区维护而不影响分区表业务流量,大大增强了分区表使用的灵活性。
MDL 系统和相关优化为 MySQL 提供了强大的并发控制能力,确保了数据库在高并发环境下的性能和稳定性。通过合理利用 MDL 系统,开发者和数据库管理员可以有效管理并发请求,提高系统性能。