- 前言
- 一、java开发之路的基石mysql组件的架构简介
- 1.1.1 Mysql的逻辑架构
- 1.1.2 连接管理与安全
- 1.1.3 优化与执行
- 1.2 并发控制
- 1.2.1 锁粒度
- 表锁
- 行级锁
- 1.3 事务(熟悉ACID可跳过)
- 1.3.1 隔离级别
- 1.3.2 死锁
- 1.3.3 事务日志
- 1.3.4 mysql中的事务
- 设置提交模式和隔离级别
- 在事务中混合使用存储引擎
- 隐式和显式锁定
- 1.4多版本并发控制
- 1.5 MySQL的存储引擎
- ✔1.5.1 InnoDB引擎
- InnoDB概览
- MyISAM存储引擎
- MyISAM特性
- MyISAM压缩表
- MyISAM性能
- 1.5.3Mysql内建的其他主要存储引擎简要介绍
- Archive引擎
- CSV引擎
- Memory引擎
- NDB集群引擎
- 1.5.4 第三方存储引擎
- OLTP类引擎
- 面向列的存储引擎
- 1.5.5 选择合适的引擎
- 1.5.6 转换表的引擎
- 1.6 Mysql架构部分总结
- 第二章.MySQL基准测试
- 2.1 为什么需要基准测试?
- 2.2 基准测试的策略
- 2.2.1 测试何种指标
- 2.3 基准测试方法
- 2.3.1 常见的错误
前言
作者刚刚研读学习了Mysql的高性能优化和架构设计.写这篇文章为了日后复习巩固和帮助后来者提炼mysql精华! 还请各位读者及时勘误联系作者.本章节将持续更新!阅读本文章,需要有一定的数据库基础.为了避免重复造轮子,本章筛选了各位领域大佬的文章并注明了出处.目的只有两个复习和总结知识共同学习.
提示:以下是本篇文章正文内容,下面案例可供参考
一、java开发之路的基石mysql组件的架构简介 1.1.1 Mysql的逻辑架构MySQL的最重要,最与众不同的特性:存储引擎架构.
这种架构的设计将查询处理及其他系统任务和数据的存储/提取相分离.这种架构模式我们可以在不同环境,不同需求下自由选择数据存储的方式.
每个客户端连接服务器进程中是安全的.都具有独立的线程.服务器会负责缓存线程.
1.1.3 优化与执行mysql: 1.解析查询 2. 创建内部数据结构 3.对sql语句优化.
1.2 并发控制只要有多个查询需要在同一时刻修改数据,都会产生并发控制的问题.
1.2.1 锁粒度1.锁粒度即衡量锁定的数据量.
2.研究锁粒度为了平衡锁的开销和数据的安全性. 而MySQL则提供了多种选择。每种MySQL存储引擎都可以实现自己的锁策略和锁粒度.提供了面对不同场景的灵活解决方案.以下介绍两种最重要的锁策略.
1.表锁是MySQL中最基本的锁策略,并且是开销最小的策略。类似于读写锁.
2.存储引擎可以管理自己的锁,但MySQL服务器层还是会使用各种有效的表锁来实现不同的目的。
1.行级锁可以最大程度地支持并发处理(同时也带来了最大的锁开销)。
2.行级锁只在存储引擎层实现,而MySQL服务器层没有实现。
事务内的语句,要么全部执行成功,要么全部执行失败。这是为了保证数据信息的安全性.
一个运行良好的事务处理系统, 必须具备这些标准特征:
| 原子性 | 一个事务必须被视为一个不可分割的最小工作单元,整个事务 中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性。 |
| 一致性 | 数据库总是从一个一致性的状态转换到另外一个一致性的状态。 |
| 隔离性 | 一个事务所做的修改在最终提交以前,对其他事务 是不可见的。 |
| 持久性 | 一旦事务提交,则其所做的修改就会永久保存到数据库中。此 时即使系统崩溃,修改的数据也不会丢失。 |
需要强调的是InnoDB和XtraDB存储引 擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)在REPEATABLE READ(可重复读)解决了幻读的问题。稍后在多版本并发控制(MVCC)中详细讨论.
详见这位博主 什么是脏读、不可重复读(提交读),幻读
1.3.2 死锁1.如果凑巧,两个事务都执行了第一条UPDATe 语句,会出现互相锁定,然后两个事务都等待对方释放锁, 同时又持有对方需要的锁,则陷入死循环。(除非有外部因素介入才可能 解除死锁。)
为了解决这种问题,数据库系统实现了各种死锁检测和死锁超时机制。越复杂的系统,比如InnoDB存储引擎,越能检测到死锁的循环依赖,并立即返回一个错误。这种解决方式很有效,否则死锁会导致出现非常慢的查询。InnoDB目前处理死锁的方法是,将持有最少行级排他锁的事务进行回滚(这是相对比较简 单的死锁回滚算法)。
3.死锁的原因:(1)真正的数据冲突 (2)存储引擎的实现方式导致的.
1.3.3 事务日志事务日志可以帮助提高事务的效率。事务日志采用的是追加的方式,因此写日志的操作是磁盘上一小块区域内的 顺序I/O.
我们通常称之为预写式日志(Write-Ahead Logging),修改数据需要写两次磁盘。
如果数据的修改已经记录到事务日志并持久化,但数据本身还没有 写回磁盘,此时系统崩溃,存储引擎在重启时能够自动恢复这部分修改 的数据。具体的恢复方式则视存储引擎而定。
MySQL提供了两种事务型的存储引擎:InnoDB和NDB Cluster。
设置提交模式和隔离级别值为 0 和值为 OFF:关闭事务自动提交。如果关闭自动提交,用户将会一直处于某个事务中,只有提交或回滚后才会结束当前事务,重新开始一个新事务。
值为 1 和值为 ON:开启事务自动提交。如果开启自动提交,则每执行一条 SQL 语句,事务都会提交一次。
-- 修改提交模式 set session autocommit=0; //会话的事务提交模式 show session variables like 'autocommit'; set global autocommit=0; //全局的事务提交模式 show global variables like 'autocommit'; ROLLBACK; COMMIT; //隔离级别操作 //mysql5.7及之后版本 show variables like 'transaction_isolation';或者select @@transaction_isolation; //mysql5.7之前版本 show variables like 'tx_isolation';或者select @@tx_isolation; //设置read uncommitted级别: set session transaction isolation level read uncommitted; //设置read committed级别: set session transaction isolation level read committed; //设置repeatable read级别: set session transaction isolation level repeatable read; //设置serializable级别: set session transaction isolation level serializable;在事务中混合使用存储引擎
MySQL服务器层不管理事务,事务是由下层的存储引擎实现的。 所以在同一个事务中,使用多种存储引擎是不可靠的。事务需要回滚,非事务型的表上的变更就无法撤销,这会 导致数据库处于不一致的状态,这种情况很难修复,事务的最终结果将 无法确定。所以,为每张表选择合适的存储引擎非常重要。
隐式和显式锁定InnoDB采用的是两阶段锁定协议(two-phase locking protocol)。在事务执行过程中,随时都可以执行锁定,锁只有在执行COMMIT 或者ROLLBACK 的时候才会释放,并且所有的锁是在同一时刻被释放。InnoDB会根据隔离级别在需要的时候自动加锁。
LOCK TABLES 和事务之间相互影响的话,情况会变得非常复杂,在某些MySQL版 本中甚至会产生无法预料的结果。除了事务中禁用了AUTOCOMMIT ,可以使用LOCK TABLES 之外,其他任何时候都不要显式地执行LOCK TABLES ,不管使用的是什么存储引擎.
1.4多版本并发控制大多数数据库的大多数事务型存储引擎实现的都不是简单的行级锁。基 于提升并发性能的考虑,它们一般都同时实现了多版本并发控制 (MVCC)。MVCC是行级锁的一个变种,大都实现了非阻塞的读操作,写操作也只锁定必要的行,因此开销更低。
MVCC的实现,是通过保存数据在某个时间点的快照来实现的。不同存储引擎的MVCC实现是不同的.InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现 的。这两个列,一个保存了行的创建时间,一个保存行的过期时间(或 删除时间)。当然存储的并不是实际的时间值,而是系统版本号.
下面看一下在REPEATABLE READ 隔离 级别下,MVCC具体是如何操作的。
SELECT InnoDB会根据以下两个条件检查每行记录:
a. InnoDB只查找版本早于当前事务版本的数据行(也就是,行的系统版本号小于或等于事务的系统版本号),这样可以确保事务读取的行,要么是在事务开始前已经存在 的,要么是事务自身插入或者修改过的。
b. 行的删除版本要么未定义,要么大于当前事务版本号。这 可以确保事务读取到的行,在事务开始之前未被删除。
只有符合上述两个条件的记录,才能返回作为查询结果。
INSERT
InnoDB为新插入的每一行保存当前系统版本号作为行版本号。
DELETE
InnoDB为删除的每一行保存当前系统版本号作为行删除标识。
UPDATE
InnoDB为插入一行新记录,保存当前系统版本号作为行版本 号,同时保存当前系统版本号到原来的行作为行删除标识
保存这两个额外系统版本号,使大多数读操作都可以不用加锁。这 样设计使得读数据操作很简单,性能很好,并且也能保证只会读取到符合标准的行。不足之处是每行记录都需要额外的存储空间,需要做更多的行检查工作,以及一些额外的维护工作.
MVCC在mysql下只在REPEATABLE READ 和READ COMMITTED 两个隔离级别下工作.其他两个隔离级别都和MVCC不兼容 ,因为READ UNCOMMITTED 总是读取最新的数据行,而不是符合当前事务版本的数据行.而SERIALIZABLE 则会对所有读取的行都加锁.
1.5 MySQL的存储引擎关于存储引擎我将大量引用mysql高性能一书的原文,它太过于重要和基础.
不同的存储引擎保存数据和索引的方式是不 同的,但表的定义则是在MySQL服务层统一处理的。这样屏蔽了不同平台的语言差异.
//查询表结构 SHOW TABLE STATUS LIKE 'members'
mysql8.0与mysql5.7的区别
InnoDB是MySQL的默认事务型引擎,也是最重要、使用最广泛的存储引擎。
它被设计用来处理大量的短期(short-lived)事务,短期事 务大部分情况是正常提交的,很少会被回滚。InnoDB的性能和自动崩 溃恢复特性,使得它在非事务型存储的需求中也很流行。除非有非常特别的原因需要使用其他的存储引擎,否则应该优先考虑InnoDB引擎。值得钻研.
InnoDB的数据存储在表空间(tablespace)中,表空间是由InnoDB 管理的一个黑盒子,由一系列的数据文件组成。在MySQL 4.1以后的版 本中,InnoDB可以将每个表的数据和索引存放在单独的文件中。 InnoDB也可以使用裸设备作为表空间的存储介质,但现代的文件系统 使得裸设备不再是必要的选择。
InnoDB采用MVCC来支持高并发,并且实现了四个标准的隔离级 别。其默认级别是REPEATABLE READ (可重复读),并且通过间隙锁 (next-key locking)策略防止幻读的出现。间隙锁使得InnoDB不仅仅锁 定查询涉及的行,还会对索引中的间隙进行锁定,以防止幻影行的插 入。
InnoDB表是基于聚簇索引建立的,我们会在后面的章节详细讨论聚簇索引。InnoDB的索引结构和MySQL的其他存储引擎有很大的不 同,聚簇索引对主键查询有很高的性能。不过它的二级索引(secondary index,非主键索引)中必须包含主键列,所以如果主键列很大的话, 其他的所有索引都会很大。因此,若表上的索引较多的话,主键应当尽 可能的小。InnoDB的存储格式是平台独立的,也就是说可以将数据和 索引文件从Intel平台复制到PowerPC或者Sun SPARC平台。
InnoDB内部做了很多优化,包括从磁盘读取数据时采用的可预测 性预读,能够自动在内存中创建hash索引以加速读操作的自适应哈希索 引(adaptive hash index),以及能够加速插入操作的插入缓冲区(insert buffer)等。本书后面将更详细地讨论这些内容。
**InnoDB的行为是非常 复杂的,不容易理解。**如果使用了InnoDB引擎,笔者强烈建议阅读官 方手册中的“InnoDB事务模型和锁”一节。如果应用程序基于InnoDB构 建,则事先了解一下InnoDB的MVCC架构带来的一些微妙和细节之处是 非常有必要的。存储引擎要为所有用户甚至包括修改数据的用户维持一 致性的视图,是非常复杂的工作。
作为事务型的存储引擎,InnoDB通过一些机制和工具支持真正的 热备份,Oracle提供的MySQL Enterprise Backup、Percona提供的开源的 XtraBackup都可以做到这一点。MySQL的其他存储引擎不支持热备份, 要获取一致性视图需要停止对所有表的写入,而在读写混合场景中,停止写入可能也意味着停止读取。
在MySQL 5.1及之前的版本,MyISAM是默认的存储引擎。 MyISAM提供了大量的特性,包括全文索引、压缩、空间函数(GIS)
等,但MyISAM不支持事务和行级锁,而且有一个毫无疑问的缺陷就是 崩溃后无法安全恢复。正是由于MyISAM引擎的缘故,即使MySQL支持 事务已经很长时间了,在很多人的概念中MySQL还是非事务型的数据 库。尽管MyISAM引擎不支持事务、不支持崩溃后的安全恢复,但它绝 不是一无是处的。对于只读的数据,或者表比较小、可以忍受修复 (repair)操作,则依然可以继续使用MyISAM(但请不要默认使用 MyISAM,而是应当默认使用InnoDB)。
存储
MyISAM会将表存储在两个文件中:数据文件和索引文件,分别 以.MYD 和.MYI 为扩展名。MyISAM表可以包含动态或者静态(长度固 定)行。MySQL会根据表的定义来决定采用何种行格式。MyISAM表可 以存储的行记录数,一般受限于可用的磁盘空间,或者操作系统中单个 文件的最大尺寸。 在MySQL 5.0中,MyISAM表如果是变长行,则默认配置只能处理 256TB的数据,因为指向数据记录的指针长度是6个字节。而在更早的 版本中,指针长度默认是4字节,所以只能处理4GB的数据。而所有的 MySQL版本都支持8字节的指针。要改变MyISAM表指针的长度(调高 或者调低),可以通过修改表的MAX_ROWS 和AVG_ROW_LENGTH 选项的值 来实现,两者相乘就是表可能达到的最大大小。修改这两个参数会导致 重建整个表和表的所有索引,这可能需要很长的时间才能完成。
作为MySQL最早的存储引擎之一,MyISAM有一些已经开发出来很 多年的特性,可以满足用户的实际需求。
加锁与并发
MyISAM对整张表加锁,而不是针对行。读取时会对需要读到 的所有表加共享锁,写入时则对表加排他锁。但是在表有读取查询 的同时,也可以往表中插入新的记录(这被称为并发插入, ConCURRENT INSERT)。
修复
对于MyISAM表,MySQL可以手工或者自动执行检查和修复操 作,但这里说的修复和事务恢复以及崩溃恢复是不同的概念。执行 表的修复可能导致一些数据丢失,而且修复操作是非常慢的。可以 通过CHECK TABLE mytable 检查表的错误,如果有错误可以通过执 行REPAIR TABLE mytable 进行修复。另外,如果MySQL服务器已 经关闭,也可以通过myisamchk 命令行工具进行检查和修复操作。
索引特性
对于MyISAM表,即使是BLOB和TEXT等长字段,也可以基于其前500个字符创建索引。MyISAM也支持全文索引,这是一种基 于分词创建的索引,可以支持复杂的查询。
延迟更新索引键(Delayed Key Write)
创建MyISAM表的时候,如果指定了DELAY_KEY_WRITE 选项,
在每次修改执行完成时,不会立刻将修改的索引数据写入磁盘,而 是会写到内存中的键缓冲区(in-memory key buffer),只有在清理 键缓冲区或者关闭表的时候才会将对应的索引块写入到磁盘。这种 方式可以极大地提升写入性能,但是在数据库或者主机崩溃时会造 成索引损坏,需要执行修复操作。延迟更新索引键的特性,可以在 全局设置,也可以为单个表设置。
如果表在创建并导入数据以后,不会再进行修改操作,那么这样的 表或许适合采用MyISAM压缩表。 可以使用myisampack 对MyISAM表进行压缩(也叫打包pack)。压 缩表是不能进行修改的(除非先将表解除压缩,修改数据,然后再次压 缩)。压缩表可以极大地减少磁盘空间占用,因此也可以减少磁盘 I/O,从而提升查询性能。压缩表也支持索引,但索引也是只读的。 以现在的硬件能力,对大多数应用场景,读取压缩表数据时的解压 带来的开销影响并不大,而减少I/O带来的好处则要大得多。压缩时表 中的记录是独立压缩的,所以读取单行的时候不需要去解压整个表(甚 至也不解压行所在的整个页面)。
MyISAM性能MyISAM引擎设计简单,数据以紧密格式存储,所以在某些场景下 的性能很好。MyISAM有一些服务器级别的性能扩展限制,比如对索引
键缓冲区(key cache)的Mutex锁,MariaDB基于段(segment)的索引 键缓冲区机制来避免该问题。但MyISAM最典型的性能问题还是表锁的 问题,如果你发现所有的查询都长期处于“Locked”状态,那么毫无疑问表锁就是罪魁祸首。
1.Archive存储引擎只支持INSERT 和SELECT 操作.
2.Archive引擎会缓存所有的写并利用zlib对插入的行进行压缩,所以 比MyISAM表的磁盘I/O更少。但是每次SELECT查询都需要执行全表扫 描。所以Archive表适合日志和数据采集类应用.
3.Archive引擎支持行级锁和专用的缓冲区,所以可以实现高并发的插入。
4.Archive引擎是一个针对高速插入和压缩做了优化的简单引擎。
1.可以将普通的CSV文件(逗号分割值的文件)作为MySQL 的表来处理,但这种表不支持索引。
2.可以将Excel等电子表格软件中的数据存储为CSV文件.
3.CSV引擎可以作为一种数据交 换的机制,非常有用.
1.如果需要快速地访问数据,并且这些数据不会被修改,重启以后丢 失也没有关系,那么使用Memory表(以前也叫做HEAP表)是非常有用 的。Memory表至少比MyISAM表要快一个数量级,因为所有的数据都 保存在内存中,不需要进行磁盘I/O。Memory表的结构在重启以后还会 保留,但数据会丢失。
2.Memory表支持Hash索引,因此查找操作非常快。
3.Memroy表是表级 锁,因此并发写入的性能较低。它不支持BLOB 或TEXT 类型的列,并且 每行的长度是固定的.
NDB集群引擎Memroy表在很多场景可以发挥好的作用:
用于查找(lookup)或者映射(mapping)表,例如将邮编和州名 映射的表。
用于缓存周期性聚合数据(periodically aggregated data)的结果。
用于保存数据分析中产生的中间数据.
NDB集群存储引擎,作为SQL和NDB原生协议之间的接口。MySQL服务器、NDB集群存储引擎,以及分布式的、share-nothing 的、容灾的、高可用的NDB数据库的组合,被称为MySQL集群 (MySQL Cluster)。后续会有章节专门来讨论MySQL集群。
1.5.4 第三方存储引擎 OLTP类引擎XtraDB可以作为InnoDB的一个完全的替代 产品,甚至可以兼容地读写InnoDB的数据文件,并支持InnoDB的所有查询。
它的改进点主要集中在性能、可测量性和操作灵活性方面。
PBXT存储引擎.它支持引擎级别的复制、外键约束,并且以一 种比较复杂的架构对固态存储(SSD)提供了适当的支持,还对较大的 值类型如BLOB也做了优化。支持 ACID事务和MVCC。PBXT是一款社区支持的存储引擎, MariaDB包含了该引擎。
面向列的存储引擎MySQL默认是面向行的,每一行的数据是一起存储的,服务器的 查询也是以行为单位处理的。而在大数据量处理时,面向列的方式可能 效率更高。如果不需要整行的数据,面向列的方式可以传输更少的数 据。如果每一列都单独存储,那么压缩的效率也会更高。
Infobright是最有名的面向列的存储引擎。在非常大的数据量(数十TB)时,该引擎工作良好。
数据高度压缩,按照块进行排序,每个块都对应有一组元数据.在处理查询时,访问元数据可决定跳过该块,甚至可能只需要元数据即 可满足查询的需求。但该引擎不支持索引.
除非 需要用到某些InnoDB不具备的特性,并且没有其他办法可以替代,否 则都应该优先选择InnoDB引擎!
例如,如果要用到全文索引,建议优 先考虑InnoDB加上Sphinx的组合,而不是使用支持全文索引的 MyISAM。当然,如果不需要用到InnoDB的特性,同时其他引擎的特性 能够更好地满足需求,也可以考虑一下其他存储引擎。举个例子,如果 不在乎可扩展能力和并发能力,也不在乎崩溃后的数据丢失问题,却对 InnoDB的空间占用过多比较敏感,这种场合下选择MyISAM就比较合适。
不建议混合使用多种存储引擎!!
应用需要不同的存储引擎需要考虑以下因素:
事务
备份
崩溃恢复
特有的特性
你不需要现在就做决定。接下来会提供很多关于各种存储引擎优缺点的详细描述,也会讨论一些架构设计的技巧。
日志型应用: MyISAM或者Archive存储引擎对这类应用比较合适,因为它们 开销低,而且插入速度非常快。
只读或者大部分情况下只读的表 如果不介意 MyISAM的崩溃恢复问题,选用MyISAM引擎是合适的。不要低估崩溃恢复问题的重要性.(一个值得推荐的方式,是在性能测试环境模拟真实的环境,运行应用,然后拔下电 源模拟崩溃测试。对崩溃恢复的第一手测试经验是无价之宝,可以避免真的碰到崩溃时手足无措)
订单处理 InnoDB是订单处理类应用的最佳选择.
电子公告牌和主题讨论论坛
当设计上述类型的应用时,建议采用InnoDB。MyISAM引擎在一开 始可能没有任何问题,但随着应用压力的上升,则可能迅速恶化。各种 锁争用、崩溃后的数据丢失等问题都会随之而来。
大数据量 如果数据量继续增长到10TB以上的级别,可能就需要建立数据仓 库。Infobright是MySQL数据仓库最成功的解决方案。也有一些大数据 库不适合Infobright,却可能适合TokuDB。
创建与查询(CREATE和SELECT)
该转换的技术综合了ALTER TABLE语法的高效和导出与导入方法的安全.不需要导出整个表的数据,而是先创建一个新的存储引擎的表,然后利 用INSERT…SELECT 语法来导数据:
CREATE TABLE innodb_table LIKE myisam_table; ALTER TABLE innodb_table ENGINE=InnoDB; INSERT INTO innodb_table SELECT * FROM myisam_table;
数据量不大的话,这样做工作得很好。如果数据量很大,则可以考 虑做分批处理,针对每一段数据执行事务提交操作,以避免大事务产生 过多的undo。假设有主键字段id ,重复运行以下语句(最小值x 和最大 值y 进行相应的替换)将数据导入到新表:
START TRANSACTION; INSERT INTO innodb_table SELECt * FROM myisam_table -> WHERe id BETWEEN x AND y; COMMIT;
这样操作完成以后,新表是原表的一个全量复制,原表还在,如果 需要可以删除原表。如果有必要,可以在执行的过程中对原表加锁,以 确保新表和原表的数据一致。 Percona Toolkit提供了一个pt-online-schema-change 的工具(基于 Facebook的在线schema变更技术),可以比较简单、方便地执行上述过 程,避免手工操作可能导致的失误和烦琐。
1.6 Mysql架构部分总结Mysql白皮书,版本更新历程
MySQL拥有分层的架构。上层是服务器层的服务和查询执行引擎,下层则是存储引擎。虽然有很多不同作用的插件API,但存储引擎 API还是最重要的。如果能理解MySQL在存储引擎和服务层之间处理查 询时如何通过API来回交互,就能抓住MySQL的核心基础架构的精髓。
MySQL最初基于ISAM构建(后来被MyISAM取代),其后陆续添 加了更多的存储引擎和事务支持。MySQL有一些怪异的行为是由于历 史遗留导致的。例如,在执行ALTER TABLE 时,MySQL提交事务的方式 是由于存储引擎的架构直接导致的,并且数据字典也保存在.frm 文件中 (这并不是说InnoDB会导致ALTER变成非事务型的。对于InnoDB来 说,所有的操作都是事务)。
当然,存储引擎API的架构也有一些缺点。有时候选择多并非好 事,而在MySQL 5.0和MySQL 5.1中有太多的存储引擎可以选择。 InnoDB对于95%以上的用户来说都是最佳选择,所以其他的存储引擎 可能只是让事情变得复杂难搞,当然也不可否认某些情况下某些存储引 擎能更好地满足需求。
Oracle一开始收购了InnoDB,之后又收购了MySQL,在同一个屋檐 下对于两者都是有利的。InnoDB和MySQL服务器之间可以更快地协同 发展。MySQL依然基于GPL协议开放全部源代码,社区和客户都可以获 得坚固而稳定的数据库,MySQL正在变得越来越可扩展和有用。
基准测试(benchmark)是MySQL新手和专家都需要掌握的一项基本技能。基准测试是针对系统设计的一种压力测试。
本章将讨论MySQL和基于MySQL的应 用的基准测试的重要性,策略和工具。
基准测试可以完成以下工作,或者更多:
1.验证基于系统的一些假设,确认这些假设是否符合实际情况。
2.重现系统中的某些异常行为,以解决这些异常。
3.测试系统当前的运行情况。如果不清楚系统当前的性能,就无法确认某些优化的效果如何。也可以利用历史的基准测试结果来分析诊断一些无法预测的问题。
4.模拟比当前系统更高的负载,以找出系统随着压力增加而可能遇到 的扩展性瓶颈。
5. 规划未来的业务增长。基准测试可以评估在项目未来的负载下,需要什么样的硬件,需要多大容量的网络,以及其他相关资源。这有
6.助于降低系统升级和重大变更的风险。
7.测试应用适应可变环境的能力。例如,通过基准测试,可以发现系统在随机的并发峰值下的性能表现,或者是不同配置的服务器之间 的性能表现。基准测试也可以测试系统对不同数据分布的处理能力。
8.测试不同的硬件、软件和操作系统配置。比如RAID 5还是RAID 10 更适合当前的系统?如果系统从ATA硬盘升级到SAN存储,对于随机写性能有什么帮助?Linux 2.4系列的内核会比2.6系列的可扩展性 更好吗?升级MySQL的版本能改善性能吗?为当前的数据采用不同的存储引擎会有什么效果?所有这类问题都可以通过专门的基准 测试来获得答案。
9.证明新采购的设备是否配置正确。笔者曾经无数次地通过基准测试来对新系统进行压测,发现了很多错误的配置,以及硬件组件的失 效等问题。因此在新系统正式上线到生产环境之前进行基准测试是一个好习惯,永远不要相信主机提供商或者硬件供应商的所谓系统 已经安装好,并且能运行多快的说法。如果可能,执行实际的基准测试永远是一个好主意。
注意:
基准测试还可以用于其他目的,比如为应用创建单元测试套件。
基准测试的一个主要问题在于其不是真实压力的测试。
大部分压力测试工具不支持对压力进行复杂的控制。务必要记住,测试工具自身的局限也会影响到结果的有效性。
结论就是,我们只能进行大概的测试,来确定系统大致的余量有多少。
基准测试有两种主要的策略:
1.针对整个系统的整体测试.
2.单独测试MySQL.
这两种策略也被称为集成式(full-stack)以及单组 件式(single-component)基准测试。
针对整个系统做集成式测试,而不 是单独测试MySQL的原因主要有以下几点:
1.测试整个应用系统,包括Web服务器、应用代码、网络和数据库是 非常有用的,因为用户关注的并不仅仅是MySQL本身的性能,而是应用整体的性能。
2.MySQL并非总是应用的瓶颈,通过整体的测试可以揭示这一点。
3.只有对应用做整体测试,才能发现各部分之间的缓存带来的影响。
4.整体应用的集成式测试更能揭示应用的真实表现,而单独组件的测 试很难做到这一点。
另外一方面,应用的整体基准测试很难建立,甚至很难正确设置。
基于以下情况,可以选择只测试 MySQL:
2.2.1 测试何种指标需要比较不同的schema或查询的性能。
针对应用中某个具体问题的测试。
为了避免漫长的基准测试,可以通过一个短期的基准测试,做快速的“周期循环”,来检测出某些调整后的效果。
请考虑以下指标,看看如何满足测试的需求。
吞吐量
吞吐量指的是单位时间内的事务处理数。这一直是经典的数据 库应用测试指标。一些标准的基准测试被广泛地引用,如TPC-C(参考http://www.tpc.org )。这类基准测试主要针对在线事务处理(OLTP)的吞吐量,非常适用于多用户的交互式应用。常用的测 试单位是每秒事务数(TPS),有些也采用每分钟事务数 (TPM)
响应时间或者延迟
这个指标用于测试任务所需的整体时间。通常可以使用百分比响应时间 (percentile response time)来替代最大响应时间。
并发性
并发性指同一时刻用户向服务器发送的请求量.并发性测试通常不是为了 测试应用能达到的并发度,而是为了测试应用在不同并发下的性
能。当然,数据库的并发性还是需要测量的。可以通过sysbench 指 定32、64或者128个线程的测试,然后在测试期间记录MySQL数据库的Threads_running 状态值。在第11章将讨论这个指标对容量规 划的影响。
可扩展性
在系统的业务压力可能发生变化的情况下,测试可扩展性就非常必要了。可扩展性指的是,给系统增加一倍的工作,在理想情况下就能获得两倍的结果(即吞吐量增加一倍)。
归根结底,应该测试那些对用户来说最重要的指标。因此应该尽可 能地去收集一些需求,比如,什么样的响应时间是可以接受的,期待多 少的并发性,等等。然后基于这些需求来设计基准测试,避免目光短浅 地只关注部分指标,而忽略其他指标.
2.3 基准测试方法 2.3.1 常见的错误使用真实数据的子集而不是全集。例如应用需要处理几百GB的数 据,但测试只有1GB数据;或者只使用当前数据进行测试,却希望
模拟未来业务大幅度增长后的情况。
使用错误的数据分布。例如使用均匀分布的数据测试,而系统的真 实数据有很多热点区域(随机生成的测试数据通常无法模拟真实的 数据分布)。
使用不真实的分布参数,例如假定所有用户的个人信息(profile) 都会被平均地读取.
在多用户场景中,只做单用户的测试。
在单服务器上测试分布式应用。
与真实用户行为不匹配。例如Web页面中的“思考时间”。真实用户 在请求到一个页面后会阅读一段时间,而不是不停顿地一个接一个 点击相关链接。
反复执行同一个查询。真实的查询是不尽相同的,这可能会导致缓 存命中率降低。而反复执行同一个查询在某种程度上,会全部或者 部分缓存结果。
没有检查错误。如果测试的结果无法得到合理的解释,比如一个本 应该很慢的查询突然变快了,就应该检查是否有错误产生。否则可 能只是测试了MySQL检测语法错误的速度了。基准测试完成后, 一定要检查一下错误日志,这应当是基本的要求。
忽略了系统预热(warm up)的过程。例如系统重启后马上进行测 试。有时候需要了解系统重启后需要多长时间才能达到正常的性能 容量,要特别留意预热的时长。反过来说,如果要想分析正常的性 能,需要注意,若基准测试在重启以后马上启动,则缓存是冷的、 还没有数据,这时即使测试的压力相同,得到的结果也和缓存已经装满数据时是不同的。
使用默认的服务器配置。第3章将详细地讨论服务器的优化配置。
测试时间太短。基准测试需要持续一定的时间。后面会继续讨论这个话题。
| 更新次数 | 更新时间 |
|---|---|
| 首发 | 2021.10.25 |
| 第一次更新 | 2021.10.26 1.删除了书中大量不必要的存储引擎类型 2.摘要完毕Mysql架构与历史部分 |
| 第二次更新 | 21.10.27 1.摘要了基准测试的部分内容 2.删除了书中大量对概念的举例. |



