---
title: MySQL OLTP 场景 TPS 瓶颈分析与 lock_sys 锁拆分-官方技术文章-鲲鹏社区
description: MySQL OLTP 场景 TPS 瓶颈分析与 lock_sys 锁拆分
keywords: MySQL,OLTP,场景,TPS,瓶颈分析与,锁拆分,官方技术文章,鲲鹏社区
url: https://www.hikunpeng.com/developer/techArticles/20260317-1?envFlag=1
section: (其他)
---

# MySQL OLTP 场景 TPS 瓶颈分析与 lock_sys 锁拆分-官方技术文章-鲲鹏社区

URL: https://www.hikunpeng.com/developer/techArticles/20260317-1?envFlag=1
描述: MySQL OLTP 场景 TPS 瓶颈分析与 lock_sys 锁拆分
关键词: MySQL,OLTP,场景,TPS,瓶颈分析与,锁拆分,官方技术文章,鲲鹏社区

官方技术文章 [了解详情](https://www.hikunpeng.com/zh/developer/techArticles)

MySQL OLTP 场景 TPS 瓶颈分析与 lock_sys 锁拆分

MySQL OLTP 场景 TPS 瓶颈分析与 lock_sys 锁拆分

mysql性能调优数据库

发表于 2026/03/17

0

# 背景

在 OLTP 场景里，当 update、insert、delete 等写操作占比较高时，系统吞吐量不一定能够达到理论峰值，可能会受到 MySQL 内的全局 latch 影响，从而达到性能瓶颈。

在实际业务中，通常可以观察到以下现象：

-   CPU 利用率较低，并且随着并发数增加基本没有明显变化。

-   TPS 或 QPS在到达一定峰值后无法继续提高。

-   使用perf进行火焰图分析，发现 off-cpu 中锁相关热点函数占比大。

这些现象说明，性能瓶颈可能不在 SQL 本身，而在数据库内部的并发控制。

### 图 1  sysbench 只写 off-cpu

下面将先解释 lock_sys 的工作方式，再看为什么锁拆分可以缓解这个问题。

# 原理

MySQL 中的每个表和行都可以看作是一种资源，事务可以请求访问资源。但是并发的事务对资源的访问可能造成冲突，因此 MySQL 设计了 Lock-sys 用于管理对表和行的访问。

Lock-sys 维护多个锁队列，管理事务对表和行资源的占用与等待。

当一个新请求需要申请某个资源的时候，Lock-sys需要完成：

1.  在相应队列里查询资源是否已被占用；

2.  将请求入队（已授权或等待）；将锁请求插入到相应的队列中（不管请求的资源是否被占用，分别标记为已授权或等待锁请求）。

3.  更新数据等待状态。

以上所有的查询与插入步骤都需要进行队列加锁保护。

数据库中，lock 和 latch 有时都被称为锁，但意义不同：

-   lock：数据库对象锁（表锁、行锁），用于事务隔离语义。

-   latch：内存结构保护锁，用于保护内部共享结构。

在过去，所有队列的访问均由一个 latch 管理，这意味着即使只要访问一个队列，其他所有的队列也会被锁住。这种实现方式在高并发场景下效率低下，为了解决这个问题，可以引入一种更细粒度的 latch 锁定方法。

从这里开始，核心问题就变成了：如何减少“不同队列之间的互相等待”。

## 1. 旧 latch

在 MySQL 中，所有的队列访问由同一个全局 latch 管理。

即使两个事务访问的是不同队列，但也要先竞争同一把锁，导致其他所有的队列也会被锁住，这种实现方式在高并发场景下效率低下。

## 2. 新 latch

新的 latch 锁定方法是在原来全局大锁的基础上，把队列分为固定数量的 shard，每个 shard 用自己的 mutex 保护；同时保留一个全局大锁 global latch（读写锁）。

可以满足如下场景需求：

-   普通访问：对各个队列进行访问，先拿 global latch 的共享锁（s-latch），再获取相应 shard 的 mutex。（例如 MySQL 访问一条记录时，先对表加意向锁，再对相应记录加锁）

-   全局场景：在一些特殊场景下需要锁住所有队列，直接拿 global latch 的排他锁（x-latch）。

不同事务访问不同队列时，不需要再被同一个全局锁锁定，可以独立于对其他队列进行操作。

### 图 2  全局 latch 管理关系

新的 latch 锁效率提升如下图所示。在过去，如果事务 A 和事务 B 分别要访问队列 1 和队列 2，由于都需要对全局大锁上锁，这时事务 B 就会被阻塞；而在新方案里，事务 A 和事务 B 可以同时申请 global latch 的共享锁，再分别申请 mutex1 和 mutex2，也就是说事务 A 和事务 B 可以同时进行，并发度提升。

### 图 3  全局锁与分片锁并发效率对比

# 设计与实现

基于上面的原理，我可以通过以下步骤来优化锁，实现功能。

## 1. 双队列访问

访问两个队列获取两条记录时，过程如下：

1.  对 global_latch 执行 s-latch；

2.  标识记录所属的两个页；

3.  标识包含给定页队列的两个哈希桶；

4.  标识包含这两个桶的两个 shard id；

5.  按地址顺序对两个分片 mutex 上锁。

以上所有步骤（除步骤2外，因为我们通常已经知道这些页）可通过一行代码完成：

```
locksys::Shard_latches_guard guard{*block_a, *block_b};
```

## 2. 全局暂停场景

如果需要 stop-the-world，只需对 global latch 上 x-latch：

```
locksys::Exclusive_global_latch_guard guard{};
```

# 结论

从“背景现象 -> 原理分析 -> 设计实现”串起来看，锁拆分的目标就是减少无关队列之间的串行等待，提升高并发写场景下的有效吞吐。

通过锁拆分技术可使 TPC-C 综合性能提升 10%。

本页内容
