《高性能MySQL》笔记一
在大规模水平集群的架构设计中,开源的MySQL受到的关注度越来越高。到2012年整个淘宝网的核心交易系统已经全部运行在基于PC服务器的MySQL数据库集群中。
第1章 MySQL架构与历史
MySQL最重要、最与众不同的特性是它的存储引擎架构,这种架构的设计将查询处理(Query Processing)及其他系统任务(Server Task)和数据的存储/提取相分离。这种处理和存储相分离的设计可以在使用时根据性能、特性,以及其他需求来选择数据存储的方式。
1.1 MySQL逻辑架构
第一层 客户端
第二层 服务器层 包含大多数MySQL核心服务功能,包括查询解析、分析、优化、缓存以及所有的内置函数。所有跨存储引擎的功能都在这一层实现:存储过程、触发器、视图等;
第三层 存储引擎 存储引擎不会去解析SQL,不同存储引擎之间也不会相互通信。(InnoDB会解析外键定义,这是一个例外)
1.1.1 连接管理与安全性
每个客户端连接都会在服务器进程中拥有一个线程。服务器会缓存线程,因此不需要为每个新建的连接创建或者销毁线程(MySQL5.5支持线程池插件)。
1.1.2 优化与执行
MySQL会解析查询,并创建内部数据结构(解析树),然后对其进行各种优化,包括重写查询、决定表的读取顺序,以及选择合适的索引等。用户可以通过特殊的关键字提示(hint)优化器,影响它的决策过程。也可以请求优化器解释(explain)优化过程的各个因素,使用户可以知道服务器是如何进行优化决策的,并提供一个参考基准,便于用户重构查询和schema、修改相关配置,使应用尽可能高效运行。
优化器并不关心表使用的是什么存储引擎,但存储引擎对于优化查询是有影响的。因为优化器会请求存储引擎提供容量或者某个具体操作的开销信息,以及表数据的统计信息等。
对于SELECT语句,在解析查询前,服务器会先检查查询缓存(Query Cache),如果能够在其中找到对应的查询,服务器就不必再执行查询解析、优化和执行的整个过程,而是直接返回查询缓存中的结果集。(详见第7章)
1.2 并发控制
两个层面:服务器层、存储引擎层
1.2.1 读写锁
读锁,也叫共享锁(shared lock),不阻塞读锁,但是阻塞写锁;
写锁,也叫排他锁(exclusive lock),会阻塞其他的写锁和读锁;
1.2.2 锁粒度
由于加锁也要消耗资源,所以理想方式是精确的锁定。所谓锁策略,就是在锁的开销和数据的安全性之间寻求平衡。MySQL支持多个存储引擎的架构,每种MySQL存储引擎都可以实现自己的锁策略和锁粒度。
两种重要的锁策略:表锁(table lock)和行级锁(row lock)
服务器会为诸如ALTER TABLE之类的语句使用表锁,而忽略存储引擎的锁机制。
InnoDB和XtraDB,以及其它一些存储引擎中实现了行级锁(行级锁只在存储引擎层实现,服务器层没有实现)。/
1.3 事务
事务就是一组原子性的SQL查询,或者说一个独立的工作单元。
START TRANSACTION
...
COMMIT;
事务的特性ACID(atomicity,consistency,isolation,durability)
1.3.1 隔离级别
ANSI SQL隔离级别
未提交读,事务可以读取未提交的数据,被称为脏读。
提交读,大多数数据库系统的默认隔离级别。有时也叫做不可重复读,因为两次执行相同的查询,可能会得到不一样的结果。
可重复读,理论上无法解决幻读(Phantom Read)。所谓幻读,指某个事务在读取某个范围的记录时,另一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围内的记录时,会产生幻行。
InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC)解决了幻读,可重复读是MysSQL默认隔离级别。
可串行化,强制事务串行执行。
1.3.2 死锁
死锁是指两个或多个事务在同一资源上相互占用,并请求对方占用的资源,从而导致恶性循环的现象。越复杂的系统,比如InnoDB存储引擎,越能检测到死锁的循环依赖,并立即返回一个错误。InnoDB目前处理死锁的方式是,将持有最少行级排他锁的事务进行回滚(这是相对比较简单的死锁回滚算法)。
锁的行为和顺序是和存储引擎相关的。以同样的顺序执行语句,有些存储引擎会产生死锁,有些则不会。死锁的产生有双重原因:有些是因为真正的数据冲突,这些情况通常很难避免,有些则完全是由于存储引擎的实现方式导致的。
1.3.3 事务日志
1.3.4 MySQL中的事务
MySQL提供了两种支持事务的存储引擎:InnoDB和NDB Cluster。另外还有一些第三方的存储引擎也支持事务,比较知名的包括XtraDB和PBXT。
InnnoDB采用的是两阶段锁定协议。
MySQL也支持LOCK TABLES 和UNLOCK TABLES,这是在服务器层实现的。
1.4 多版本并发控制(MVCC)
可以认为MVCC是行级锁的一个变种,它在大多数情况下避免了加锁,因此开销更低。虽然实现机制有所不同,但大都实现了非阻塞的读操作,写操作也只锁定必要的行。
MVCC是通过保存数据在某个时间点的快照来实现的,典型的有乐观并发控制和悲观并发控制。
MVCC只在REPEATABLE和READ COMMITTED两个隔离级别下工作。
1.5 MySQL的存储引擎
InnoDB基于聚簇索引建立。
转换表的引擎有三种方式:
1)ALTER TABLE
ALTER TABLE mytable ENGINE = InnoDB;
2) 导出与导入
3)创建与查询(CREATE和SELECT)
第2章 MySQL基准测试
这章的内容可能有些陌生,平时开发也不怎么用到。那么重不重要呢?书中第一行就告诉我们,”基准测试(benchmark)是MySQL新手和专家都需要掌握的一项基本技能“。显然,这玩意儿很重要,即使我们不是dba而只是开发。那么先牢记下这个单词,benchmark,benchmark,benchmark......
什么是基准测试?一言以蔽之:针对系统设计的一种压力测试。
通常的目标是为了掌握系统的行为。但也有其他原因,如重现某个系统状态。或者是做新硬件的可靠性测试。
2.1 Why we need benchmark
为什么基准测试很重要?因为基准测试是唯一方便有效的、可以学习系统在给定的工作负载下会发生什么的方法。
基准测试可以完成以下工作:
1、验证基于系统的假设
2、重现系统中某些异常行为
3、测试当前系统运行情况
4、模拟比当前系统更高的负载
5、规划未来业务增长
6、测试应用适应可变环境的能力
7、测试不同的硬件、软件和操作系统配置(很多是dba需要关注的,对于开发,我们需要关注mysql版本、使用不同存储引擎的影响)
8、证明新采购的设备是否配置正确。
基准测试不是真实压力测试,其施加给系统的压力相对真实压力通常较为简单。
基准测试要尽量简单直接,结果之间容易相互比较,成本低且易于执行。
2.2 strategy of benchmark
两种策略:
1、集成式(full-stack)针对整个系统
2、组件式(single-component)单独测试MySQL
2.2.1 测试何种指标
有时候需要用不同的方法测试不同的指标。比如,针对延迟(latency)和吞吐量(throughput)就需要采用不同的测试方法。以下是常见的指标:
1、吞吐量
吞吐量指的是单位时间内的事务处理数。这一直是经典的数据库应用测试指标。一些标准的基准测试被广泛地引用,如TPC-C。这类基准测试主要针对在线事务处理(OLTP)地吞吐量,非常适用于多用户地交互式应用。常用地测试单位是每秒事务数(TPS),有时也采用每分钟事务数(TPM)。
2、响应时间或者延迟
3、并发性
并发性基准测试关注的是正在工作中的并发操作,或者是同时工作中的线程数或者连接数。当并发性增加时,需要测量吞吐量是否下降,响应时间是否变长,如果是这样,应用可能就无法处理峰值压力。
可以使用sysbench测量数据库的并发性,在测试期间记录MySQL数据库的Threads_running状态值。
4、可扩展性
指的是,给系统增加一倍资源(比如两倍CPU数),就可以获得两倍吞吐量。大多数系统无法做到如此理想的线性扩展。
2.3 基准测试方法
先看下如何避免一些常见的错误,这些错误可能导致测试结果无用或者不精确:
- 使用真实数据的子集而不是全集
- 使用错误的数据分布
- 使用不真实的分布参数
- 在多用户场景中,只做了单用户测试
- 在单服务器上测试分布式应用
- 与真实用户行为不匹配
- 没有检查错误
- 忽略了系统预热
- 使用默认的服务器配置
- 测试时间太短
2.3.1 设计和规划基准测试
2.3.2 基准测试应该运行多长时间
2.3.3 获取系统性能和状态
2.3.4 获得准确的测试结果
2.3.5 运行基准测试并分析结果
2.3.6 绘图的重要性
2.4 基准测试工具
没有必要开发自己的基准测试工具,除非现有的工具确实无法满足需求
2.4.1 集成式测试工具
ab 单个URL
http_load 可以多个URL
JMeter 比ab和http_load复杂的多。它可以通过控制预热时间等参数,更加灵活地模拟真实用户的访问。JMeter拥有绘图接口,还可以对测试进行记录,然后离线重演测试结果。
2.4.2 单组件式测试工具
mysqlslap
MySQL Benchmark Suit(sql-bench)
Super Smack
Database Test Suite
Percona's TPCC-MySQL Tool
sysbench 多线程系统压测工具,支持lua脚本。
附:MYSQL的BENCHMARK()函数
2.5 基准测试案例
2.5.1 http_load
2.5.2 MySQL Benchmark Suit
2.5.3 sysbench(强烈推荐)
sysbench可以执行多种类型的基准测试,它不仅设计用来测试数据库的性能,也可以测试运行数据库的服务器的性能。
sysbench的CPU基准测试
sysbench的文件I/O基准测试
sysbench的OLTP基准测试
2.5.4 数据库测试套件中的dbt2 TPC-C测试
2.5.5 Percona的TPCC-MySQL测试工具
2.6 总结
每个MySQL的使用者都应该了解一些基准测试的知识。基准测试不仅仅是用来解决业务问题的一种实践行动,也是一种很好的学习方法。学习如何将问题分解成可以通过基准测试来获得答案的方法,就和在数学课上从文学题目中推导出方程式一样。首先正确地描述问题,之后选择合适的基准测试来回答问题,设置基准测试的持续时间和参数,运行测试,收集数据,分析结果数据,这一系列的训练可以帮助你成为更好的MySQL用户。
第3章 服务器性能剖析(profiling)
3.1 性能优化简介
数据库服务器的性能用查询的响应时间来度量,单位是每个查询花费的时间。
性能剖析一般有两个步骤:测量任务所花费的时间;然后对结果进行统计和排序,将重要的任务排到前面。
在对系统进行性能剖析前,必须先要能够进行测量,这需要系统可测量化的支持。MySQL从5.5版本开始提供Performance Schema,默认关闭,到5.6版本默认打开。Performance Schema的存储引擎为专门设计的PERFORMANCE_SCHEMA引擎,普通的用户表无法设置使用这种引擎。
3.2 对应用程序进行性能剖析
推荐工具 New Relic、xhprof、Ifp或者MySQL的企业监视器 Enterprise Monitor
3.3 剖析MySQL查询
3.3.1 剖析服务器负载
使用慢查询日志(长期开启需要考虑磁盘负载,可部署日志轮转工具),建议用pt-query-digest生成剖析报告。主要关注剖析报告中的V/M列和执行计划列。V/M列提供了方差均值比的详细数据,方差均值比就是常说的离差参数。离差指数高的查询对应的执行时间的变化较大,而这类查询通常都值得去优化。
如果因为某些原因如权限不足等,无法在服务器上记录查询。有两种替代技术:
- 通过--processlist不断查看SHOW FULL PROCESSLIST的输出。
- 抓取TCP网络包,通过tcpdump将网络包保存到磁盘,然后用pt-query-digest解析并分析查询。
3.3.2 剖析单条查询
使用SHOW PROFILE
使用SHOW STATUS
3.3.3 使用性能剖析
3.4 诊断间歇性问题
3.4.1 单条查询问题还是服务器问题
3.4.2 捕获诊断数据
3.4.3 一个诊断案例
3.5 其他剖析工具
3.5.1 使用USER_STATISTICS表
3.5.2 使用strace
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构