《高性能MySQL(第3版)》读书笔记

背景

想要扎实一下SQL功底,提高一下写出来SQL语句的质量,之前慢SQL差点把生产环境数据库跑挂了,数据库操作还是非常重要的。大佬推荐《高性能MySQL(第3版)》,此篇记录下读书笔记。

第1 章 mysql 架构与历史

MySQL 逻辑架构

MySQL有一个很大的优点,非常灵活。最重要的特性就是它的存储引擎架构。将查询处理、其他系统任务、数据存储/提取分离开来。

MySQL服务器逻辑架构图

当客户端连接到服务器时,服务器要对客户端进行认证,连接成功后,服务器会继续验证该客户端是否具有执行某个特定查询的权限。

对于select语句,在解析查询之前,服务器会优先检查查询缓存。

并发控制

对于数据库来说,也就是并发读写。MySQL实现了锁系统,读锁(共享锁)和写锁(排他锁)。概括来说,读锁是共享,也就是相互不阻塞的。即不同客户端在同一时刻同时读取同一资源,是互不干扰的。写锁是排他的,也就是一个写锁会阻塞其他写锁和读锁。大多时候,MySQL锁的内部管理都是透明的。

所谓的锁策略,就是在锁的开销和数据安全之间寻求平衡。锁的粒度分为表锁和行级锁。

  • 表锁:MySQL最基本的锁策略,并且是开销最小的策略。
  • 行级锁:可以最大程度地支持并发处理,当然同时也带来了最大地锁开销。InnoDB实现了行级锁。

事务

事务就是一组原子性的SQL查询,或者说一个独立的工作单元。事务内的语句,要么全部执行成功,要么全部执行失败。

除非系统通过严格的ACID测试,否则空谈事务的概念是不够的。

  • A-原子性:对于一个事务来说,不可能只执行其中一部分操作,这就是事务的原子性。
  • C-一致性:数据库总是从一个一致性状态转换到另一个一致性的状态。
  • I-隔离性:通常来说(默认可重复读的隔离级别),一个事务所做的修改在最终提交之前,对其他事务是不可见的。
  • D-持久性:一旦事务提交,其所做的修改就会永久保存到数据库中。实际上“持久性”是一个比较模糊的概念,持久性也分不同的级别,而且不可能做到100%的持久性保证策略

隔离级别:在SQL标准中定义了四种隔离级别,每一种都规定了一个事务中所做的修改,在事务内和事务间哪些是可见的,哪些是不可见的。较低级别的隔离通常可以执行更高的并发,系统的开销也更低。

  • 未提交读

事务中的修改,即使没有提交,对其他事务也是可见的。也就产生了“脏读”。从性能来说。未提交读并不会比其他级别好太多,但却缺乏其他级别的很多好处,所以除非有非常必要的理由,是不建议使用的。

  • 提交读

一个事务从开始到提交之前,所做的任何修改对其他事务都是不可见的。也就会产生“不可重复读”,因为两次执行相同的查询,可能会得到不同的结果。

  • 可重复读

保证了同一事务中多次读取同样数据的结果一致。但是却无法解决“幻读”。幻读是指,当某个事务在读取某个范围内的记录时,另一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围内的记录时,会产生幻行。

  • 可串行化

最高的隔离级别,强制事务串行执行。在读取的每一行数据上都加锁,可能会产生大量的超时和锁争用。实际上很少使用,只有在非常需要确保数据一致性并且可以接受没有并发的情况下,才考虑使用。

死锁:指两个或多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环的现象。当多个事务试图以不同的顺序锁定资源时,就可能产生死锁。多个事务同时锁定同一资源时,也会产生死锁【这个我没太理解】。InnoDB目前处理死锁的方法是,将持有最少行级排他锁的事务进行回滚。死锁产生有双重原因,有些是因为真正的数据冲突,这种通常很难避免,但有些完全是因为存储引擎的实现方式导致的。大多数情况下,只需要重新执行因死锁回滚的事务即可。

MySQL默认采用自动提交模式,若不是显式地开始一个事务,则每个查询都被当成一个事务提交。

MySQL服务器层不管理事务,事务由下层存储引擎实现。所以在同一个事务中,使用多种存储引擎是不可靠的。

InnoDB采用的是两阶段锁定协议。在事务执行过程中,随时都可以执行锁定,锁只有在执行commit或者rollback的时候才会释放,并且所有的锁是在同一时刻被释放的。InnoDB会根据隔离级别在需要的时候自动加锁。

多版本并发控制

MySQL的大多数事务型存储引擎都不是简单的行级锁。基于提升并发性能的考虑,一般都同时实现了多版本并发控制(MVCC).可以理解MVCC为行级锁的一个变种,它在很多情况下避免了加锁操作,因此开销更低。实现了非阻塞的读操作,写操作也只锁定必要的行。MVCC的实现是通过保存数据在某个时间点的快照来实现的。根据事务开始的时间不同,每个事务对同一张表,同一时刻看到的数据可能是不一样的。

InnoDB的MVCC,是通过在每行记录后面保存两个隐藏列来实现的。这两个列,一个保存了行的创建时间,一个保存了行过期时间(或删除时间)。存储的并不是实际的时间值,而是系统版本号。每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号。举例如下:

MySQL的存储引擎

InnoDB

InnoDB是MySQL默认的事务型引擎。除非有非常特别的原因需要使用其他的存储引擎,否则应该优先考虑InnoDB引擎。

InnoDB的数据存储在表空间中,表空间是由InnoDB管理的一个黑盒子,有一系列的数据文件组成。InnoDB采用MVCC来支持高并发,默认隔离级别是可重复读,并且通过间隙锁策略防止幻读的出现。间隙锁使得InnoDB不仅锁定查询涉及的行,还会对索引中的间隙进行锁定,以防止幻影行的插入。

InnoDB表是基于聚簇索引建立的,聚簇索引对主键查询有很高的性能,但是二级索引(非主键索引)中必须包含主键列。

MyISAM

MyISAM提供了全文索引、压缩、空间函数等,但是不支持事务和行级锁,且崩溃后数据无法恢复。最典型的问题还是锁表问题。

MyISAM会将表数据存储在两个文件中:数据文件和索引文件。会将数据写到内存中,然后定期将数据刷到磁盘上。

MyISAM对整张表加锁,读取时对表加共享锁,写入时对表加排他锁。支持并发插入(读取的同时,进行写入)。

压缩表:表创建并导入数据后不再进行修改,可以使用压缩表。极大的减少磁盘空间占用,也就减少了磁盘I/O,从而提升查询性能。

Archive

适合日志和数据采集

CSV

可以作为数据交换机制

Memory

如果需要快速访问数据,且数据不会被修改,重启后数据丢失也没关系(因为是存储在内存中的),则可以使用。会比MyISAM快至少一个数据量。重启后数据会丢失,但是表结构会保留。可以用来缓存周期性的聚合数据或保存数据分析中产生的中间数据。

临时表只在单个连接中可见,连接断开时,临时表也将不存在。所以临时表和memory表是不一样的。

NDB集群引擎

MySQL集群

选择存储引擎时的考虑因素

事务、备份、崩溃恢复、特有的特性

总结

MySQL拥有分层架构,上层是服务器的服务和查询执行引擎,下层则是存储引擎。在存储引擎和服务层之间处理查询是通过API来回交互。对于InnoDB来说,所有操作都是事务。

第2 章 mysql 基准测试

基准测试是针对系统设计的一种压力测试

基准测试主要两种策略:集成式(针对整个系统的整体测试)、单组件式(单独测试MySQL)

测试指标:应该测试对用户来说重要的的指标,什么样的响应时间是可以接受的,期待多少并发等。

  • 吞吐量:单位时间的事务处理数
  • 响应时间或延迟 :平均响应时间、最小响应时间、最大响应时间、所占百分比(平均值有时候是没用的,会掩盖掉一些真实情况)
  • 并发性:并发性测试通常不是为了测试应用能达到的并发度,而是为了测试应用在不同并发下的性能。

影响测试结果的因素

  • 数据量
  • 数据分布
  • 系统预热

文档输出很重要

先收集所有的原始数据,然后再基于此做分析和过滤是一个好习惯

如果你想统治世界,就必须不断地利用“阴谋”(图形)。论绘图的重要性

第3 章 服务器性能剖析

性能的定义:响应时间

无法测量就无法有效地优化,所以第一步应该是测量时间花在了什么地方

如果优化的成本大于收益,就应当停止优化

只相信平均值是非常危险的,他会隐藏很多信息,而且无法表达全部情况

实际上,剖析应用程序一般比剖析数据库服务器更容易,而且回报更多

explain是通过估计得到结果,而通过计数器则是实际的测量结果

尽量不要用试错的方式来解决问题,首先有很大风险,其次非常低效

注意直觉,但应该只根据直觉来指导解决问题的思路,而不是用于确定系统的问题。决策应该尽量基于数据而非感觉。

第4 章 schema 与数据类型优化

第5 章 创建高性能的索引

第6 章 查询性能优化

第7 章 mysql 高级特性

第8 章 优化服务器设置

第9 章 操作系统和硬件优化

第10 章 复制

第11 章 可扩展的mysql 

第12 章 高可用性

第13 章 云端的mysql

第14 章 应用层优化

第15 章 备份与恢复

第16 章 mysql 用户工具

猜你喜欢

转载自blog.csdn.net/yxz8102/article/details/107391026