MySQL提升课程 全面讲解MySQL架构设计 Study Notes
Kierke

慕课网实战课程《MySQL提升课程 全面讲解MySQL架构设计》学习笔记

第1章 实例和故事

观察线上MySQL数据量运行情况指标

  • QPS

  • TPS

  • 并发量:同一时间处理的请求数量

  • CPU使用率

  • 磁盘IO

  • 经验:服务在高并发访问期间,不要在主库上做备份计划



有哪些主要因素影响数据库性能

  • SQL查询速度
  • 服务器硬件
  • 网卡流量
  • 磁盘IO

因素影响

超高的QPS和TPS

  • 风险:效率低下的SQL

大量的并发和超高的CPU使用率

  • 风险:
    • 大量的并发:数据库连接数被占满(MySQL最大连接数[max_connections]默认是100,在生产环境应该根据实际情况调大)
    • 超高的CPU使用率:因CPU资源耗尽而出现宕机

磁盘IO

  • 风险:吸盘IO性能突然下降(往往出现在热数据大于可用内存的情况下)
  • 解决:
    • 通过使用更快的磁盘设备来解决
    • 在大促期间(高并发流量期间),调整任务计划(大量消耗磁盘性能的任务调整从主服务器数据库调整到从数据库)
    • 做好磁盘维护和监控,及时报警

网卡流量

  • 风险:网卡IO被占满(1000Mb/8~100MB)
  • 如何避免无法连接数据库的情况:
    • (1)减少从服务器的数量(因为从服务器会从主服务器备份同步数据)
    • (2)进行分级缓存,避免出现客户端突然的大量缓存失效
    • (3)避免使用select * from进行查询(查询出没有必要的列会浪费流量)
    • (4)分离业务网络和服务器网络(避免主从同步或网络备份的影响)


大表对数据库性能的影响

  • 什么样的表可以称为大表?

    • 大表是相对而言的,对不同的存储引擎有不同的限制,以下以Innodb存储引擎为例
    • 记录行数巨大,单表超过千万行
    • 表数据文件巨大,表数据文件超过10G
  • 大表对查询的影响:

    • 慢查询:很难在一定时间内过滤出想要的数据
  • 大表对DDL的影响:

    • 风险:建立索引需要很长的时间:
      • MySQL版本 < 5.5 ,建立索引会锁表
      • MySQL版本 >= 5.6 ,虽然不会锁表但会引起主从延迟(先主库执行再从库复制,会引起延迟)
    • 修改表结构需要长时间锁表:
      • 风险:造成长时间的主从延迟(先主库执行再从库复制,会引起延迟)
      • 风险:影响正常的数据操作
  • 如何处理数据库中的大表

    • 分库分表:把一张大表分成多个小表
      • 难点:分表主键的选择(对业务非常重要)
      • 难点:分表后跨分区数据的查询和统计
    • 大表的历史数据归档(要注意减少对前端业务的影响)
      • 难点:归档时间点的选择
      • 难点:如何进行归档操作


    大事务对数据库性能的影响

    什么是事务

  • 事务是数据库系统区别于其它文件系统的重要特征之一

  • 事务是一组具有原子性的SQL语句,或是一个独立的工作单元

事务特性

原子性(ATOMICITY)

  • 一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败,对一个事务来说,不可能只执行其中的一部分操作

一致性(CONSISTENCY)

  • 一致性是指事务将数据库从一种一致性状态转移到另一种一致性状态,在事务开始前和事务结束后数据库中的数据完整性没有被破坏

隔离性(ISOLATION)

  • 一个事务对数据库中的数据进行了修改,在他提交前,对于其它事务是不可见的
  • SQL标准中定义的4种隔离级别:
    • 读未提交(READ-UNCOMMITED)
    • 读已提交(READ-COMMITED)
    • 可重复读(REPETABLE-READ)
    • 串行化(SERIALIZABLE)

持久化(DURABILITY)

  • 一旦事务提交,其所做的修改就永远保存到数据库中。即使此时数据库系统崩溃,已经提交的修改数据也不会丢失

什么是大事务

  • 运行时间比较长,操作的数据比较多的事务
  • 风险:
    • 锁定太多的数据,造成大量的阻塞和锁超时
    • 回滚时所需的时间比较长
    • 执行时间比较长,容易造成主从延迟

如何处理大事务

  • 避免一次处理太多的事务
  • 移除在事务中不必要的select操作



第2章 什么影响了MySQL性能

影响MySQL数据库性能的几个方面

  • 服务器硬件(CPU、内存、IO系统)
  • 服务器操作系统
  • 数据库存储引擎的选择
    • MyISAM:不支持事务,表级锁
    • 事务级存储引擎,完美支持行级锁,事务ACID特性
  • 数据库服务配置参数(对数据库性能影响最为巨大)
  • 数据库结构设计和SQL语句(执行效率)


服务器硬件

CPU

  • 计算密集性,CPU对性能的影响更为重要
  • 如何选择CPU,更多的CPU还是更好的CPU?
    • 我们的应用是否是CPU密集型的
    • 是否支持多CPU对同一SQL并发处理
    • 系统并发量如何
    • MySQL的版本,对多核CPU的支持情况

内存

  • 把数据缓存到内存中大大提高性能
  • MyISAM存储引擎:
    • 索引缓存到内存中
    • 数据缓存到操作系统中
  • InnoDB存储引擎:
    • 在内存中缓存索引和数据
  • 内存虽然越多越好,但对性能的影响也是有限度的
  • 缓存不仅对读有好的影响,对写也有好的影响

磁盘的配置和选择

  • 使用传统机器硬盘
  • 使用RAID增强传统机器硬盘的性能
  • 使用固态存储SSD卡和PCIe卡
  • 使用网络存储NAS和SAN

传统机器硬盘

  • 价格低
  • 使用最多
  • 最常见
  • 存储空间大
  • 读、写速度慢
  • 传统机器硬盘读取数据过程:
    • (1)移动磁头到磁盘表面上正确的位置(访问时间)
    • (2)等待磁盘旋转,使得所需的数据在磁头之下(访问时间)
    • (3)等待磁盘旋转过去,所有所需的数据都被磁头读出(传输速度)
  • 如何选取传统机器硬盘:
    • 存储容量
    • 传输速度
    • 访问时间
    • 主轴转速
    • 物理尺寸

使用RAID增强传统机器硬盘的性能

什么是RAID
  • RAID是磁盘冗余队列的简称(Redundant Arrays of Independent Disks)
  • 简单来说RAID的作用就是可以把多个容量较小的磁盘组成一组容量更大的磁盘,并提供数据几余来保证数据完整性的技术
RAID 0
  • RAID 0是最早出现的RAID模式,也称之为数据条带。是组建磁盘阵列中最简单的一种形式,只需要2块以上的硬盘即可,成本低,可以提高整个磁盘的性能和吞吐量。RAID 0没有提供冗余或错误修复能力,但是实现成本是最低的。
RAID 1
  • RAID 1又称磁盘镜像,原理是把一个磁盘的数据镜像到另一个磁盘上,也就是说数据在写入一块磁盘的同时,会在另一块闲置的磁盘上生成镜像文件,在不影响性能情况下最大限度的保证系统的可靠性和可修复性
RAID5
  • RAID5又称之为分布式奇偶校验磁盘阵列
  • 通过分布式奇偶校验块把数据分散到多个磁盘上,这样如果任何一个盘数据失效,都可以从奇偶校验块中重建。但是如果两块磁盘失效,则整个卷的数据都无法恢复。
RAID 10
  • RAID 10 又称分片的镜像
  • 它是对磁盘先做RAID 1之后对两组RAID 1的磁盘再做RAID0,所以对读写都有良好的性能,相对于RAID 5重建起来更简单,速度也更快。

RAID级别的选择

等级 特点 是否冗余 盘数
RAID0 便宜,快速,危险 N
RAID1 高速读,简单,安全 2
RAID5 安全,成本折中 N+1 取决于最慢的盘
RAID10 贵,高速,安全 2N

固态存储

  • 相比机械磁盘固态磁盘有更好的随机读写性能
  • 相比机械磁盘固态磁盘能更好的支持并发
  • 相比机械磁盘固态磁盘更容易损坏
SSD
  • 使用SATA接口,可以替换传统磁盘而不需任何改变
  • SATA接口的SSD同样支持RAID技术
PCI-E SSD
  • 无法使用SATA接口,需要独特的驱动和配置
  • 价格相对于SSD要贵,但是性能比SSD更好
固态存储的使用场景
  • 适用于存在大量随机I/O的场景
  • 适用于解决单线程负载的I/O瓶颈

网络存储SAN和NAS

  • SAN(Storage Area Network和NAS(Network-Attached storage)是两种外部文件存储设备加载到服务器上的方法
  • SAN设备通过光纤连接到服务器,设备通过块接口访问,服务器可以将其当做硬盘使用。
  • SAN:
    • 可以承受大量顺序读写,因为这些读写I/O可以缓存、I/O合并(但是数据库的性能瓶颈往往在随机IO)
    • 不如本地RAID磁盘
    • 随机读写,慢,适用大量顺序读写
  • NAS设备使用网络连接,通过基于文件的协议如NFS或SMB来访问。(有一定的网络传输延迟)
  • 网络存储适用场景
    • 数据库备份
  • 网络性能的限制和影响
    • 带宽
    • 延迟
    • 网络质量
  • 建议:
    • 采用高性能和高带宽的网络接口设备和交换机
    • 对多个网卡进行绑定,增强可用性和带宽
    • 尽可能的进行网络隔离

小结

CPU
  • 64位的CPU一定要工作在64位的系统下
  • 对于并发比较高的场景CPU的数量比频率重要
  • 对于CPU密集性场景和复杂SOL则频率越高越好
内存
  • 选择主板所能使用的最高频率的内存
  • 内存的大小对性能很重要,所以尽可能的大
  • 如果内存足够的大,就可以在数据落盘的时候把 大量的随机IO变成顺序IO(先在内存中排序)
I/O子系统
  • PCIe->SSD->Raid10>磁盘->SAN


操作系统对系统的影响

MySQL支持的操作系统

  • Windows(注意windows下大小写不敏感)
  • FreeBSD(需要使用新版本)
  • Solaris
  • Linux

CentOS系统参数优化(MySQL的优化)

1
2
3
4
5
6
7
8
9
10
# 内核相关参数 (/etc/sysctl.conf)
# 每个端口最大的监听队列的长度
net.core.somaxconn=65535
net.core.netdev_max backlog=65535
net.ipv4.tcp_max_syn_backlog=65535

# 加速tcp连接的回收
net.ipv4.tcp_fin timeout = 10
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
  • ……


文件系统对性能的影响

  • Windwos
    • FAT
    • NTFS
  • Linux
    • EXT3
    • EXT4
    • XFS(性能更高)


MySQL结构体系

概述

  • 客户端
  • MySQL服务层:连接管理器、查询缓存、查询解析、查询优化器
  • 存储引擎层:
    • innodb
    • myisam
    • XtraDB
    • CSV
    • Memory
    • MRG_MYISAM
    • archive
    • federated
    • tokudb等
  • 存储引擎是针对于表的而不是针对于库的(一个库中的不同表可以使用不同的存储引擎 )

MyISAM

  • MySQL5.5之前版本默认使用的存储引擎
  • 大部分系统表、临时表(在排序、分组等操作中,当数量超过一定的大小之后,由查询优化器建立的临时表)使用的存储引擎
  • 存储表的物理文件:
    • MYD(存储表的数据信息)
    • MYI(存储索表的引信息)
    • FRM(存储表的结构信息,所有存储引擎都有这个文件)
  • 特性
    • 锁:支持表级锁(并发性底)
    • 表损坏修复
      • 检查:check table tablename
      • 恢复:repair table tablename
    • 还可以使用 myisamchk 进行表修复,但是需要关闭数据库,否则会损坏数据库的数据
    • MyISAM表支持的索引类型:
      • 支持全文索引,MySQL5.7版本之前唯一原生就支持全文索引的存储引擎
      • 支持对text、blob字段建立前500个字符的前缀索引
      • 支持数据压缩(对只读表),命令行:myisampack。对已经压缩的表只能进行只读操作
  • 限制:
    • 版本< MySQL5.0时默认表大小为4G。如存储大表则要修改MAX Rows 和 AVG ROW_LENGTH
    • 版本>MySQL5.0时默认支持为256TB
  • 适用场景:
    • 非事务型应用(不支持事务)
    • 只读类应用(支持共享锁,可以对数据进行压缩)
    • 空间类应用(支持空间函数)

InnoDB

  • MySQL5.5之后官方默认的存储引擎

  • InnoDB是一种事务型存储引擎,支持事务ACID特性。它的设计适合处理大量的小事务

  • Innodb使用表空间进行 数据存储

    • 参数innodb_file_per _table可以指定表存储的表空间
    • innodb_file_per _table = on存储到独立表空间 tablename.ibd
    • innodb_file_per _table = off 存储到系统表空间 ibdataX
  • 系统表空间和独立表空间

    • 系统表空间无法简单的收缩文件大小(即使删除了表,或表数据,文件依然不会减小,这样会浪费存储空间)
    • 独立表空间可以通过optimize table命令收缩系统文件(且不需要重启MySQL服务)
    • 系统表空间会产生IO瓶颈(在对多个表数据进行刷新时,是顺序进行的),频繁写入的情况不适合
    • 独立表空间可以同时向多个文件刷新数据
    • 建议:对Innodb 使用独立表空间
    • MySQL5.6之前 innodb_file_per _table = off
    • MySQL5.6之后,独立表空间也成了默认的配置

在一个繁忙的系统中,表空间文件在不断增长

使用系统表空间进行文件存储:无法很容易收缩系统文件,造成磁盘空间浪费,产生大量磁盘碎片,降低系统性能

使用独立表空间:在对一个大表进行清理后使用optimize table命令收缩系统文件,无需重启服务器,不影响访问,虽然也会重建表,但比重建整个库快得多

  • 表转移的步骤(把原来存在于系统表空间中的表转移到独立表空间中的方法)
    • (1)使用mysqldump导出所有数据库表数据(存储过程、触发器、函数等等记得一起导出)
    • (2)停止MySQL服务(主从服务架构可以先停止从服务器),修改参数(innodb_file_per _table = on),并删除Innodb相关文件
    • (3)重启MySQL服务,重建Innodb系统表空间
    • (4)重新导入数据



第3章 MySQL基准测试

什么是基准测试

  • 对数据库系统性能的测试叫做基准测试
  • 什么是基准测试:
    • 基准测试是一种测量和评估软件性能指标的活动用于建立某个时刻的性能基准,以便当系统发生软硬件变化时重新进行基准测试以评估变化对性能的影响



第4章 MySQL数据库结构优化

概述

  • 对数据性能影响最大的是数据库的结构

  • 良好的数据库逻辑设计和物理设计是数据库获得高性能的基础



数据库结构优化的目的

  • 减少数据冗余
  • 尽量避免数据维护中出现更新,插入和删除异常
    • 插入异常:如果表中的某个实体随着另一个实体而存在
    • 更新异常:如果更改表中的某个实体的单独属性时,需要对多行进行更新
    • 删除异常:如果删除表中的某一实体则会导致其他实体的消失
  • 节约数据存储空间
  • 提高查询效率

数据库结构设计步骤

数据库的结构设计是根据产品需求的变更而循环往复的

  • 需求分析:全面了解产品设计的存储需求

    • 存储需求:需要存储什么样的数据?这些数据有什么特点
    • 数据处理需求:如何对数据存储、读取、修改,完成产品的设计功能,数据读取响应时间?数据处理方式是批处理还是连接处理
    • 数据的安全性和完整性
    • 数据的生命周期
  • 逻辑设计:

    • 设计数据的逻辑存储结构
    • 数据实体之间的逻辑关系,解决数据余和数据维护异常
  • 物理设计:

    • 跟据所使用的数据库特点进行表结构设计
    • 关系型数据库
    • 非关系型数据库
    • 存储引擎
  • 维护优化:跟据实际情况对索引、存储结构等进行优化



数据库设计范式

数据库设计的第一范式

  • 第一范式的目标是确保每列的原子性,
  • 数据库表中的所有字段都只具有单一属性,单一属性的列是由基本的数据类型所构成的
  • 设计出来的表都是简单的二维表

数据库设计的第二范式

  • 满足第一范式,任何一个非主键字段的数值都依赖于主键字段
  • 要求一个表中只具有一个业务主键,也就是说符合第二范式的表中不能存在非主键列对只对部分主键的依赖关系

数据库设计的第三范式

  • 若一个关系满足第一范式(1NF)和第二范式(2NF),任何两个非主键字段的数值之间不存在函数依赖关系,则满足第三范式(3NF)

  • 指每一个非主属性既不部分依赖于也不传递依赖于业务主键,也就是在第二范式的基础上消除了非主属性对主键的传递依赖

范式化设计 & 反范式化设计

范式化设计的优缺点

  • 优点:
    • 可以尽量的减少数据冗余,数据表更新快体积小
    • 范式化的更新操作比反范式化更快
    • 范式化的表通常比反范式化更小
  • 缺点:
    • 对于查询需要对多个表进行关联
    • 更难进行索引优化

反范式化设计的优缺点

  • 优点:
    • 可以减少表的关联
    • 可以更好的进行索引优化
  • 缺点:
    • 存在数据冗余及数据维护异常
    • 对数据的修改需要更多的成本


数据库物理设计

概述

  • 根据所选择的关系型数据库的特点对逻辑模型进行存储结构设计
  • 物理设计涉及的内容:
    • 定义数据库、表及字段的命名规范
    • 选择合适的存储引擎
    • 为表中的字段选择合适的数据类型
    • 建立数据库结构

定义数据库、表及字段的命名规范

  • 数据库、表及字段的命名要遵守可读性原则、遵守表意性原则、遵守长名原则

选择合适的存储引擎

存储引擎 事务 锁粒度 主要应用 忌用
MyISAM 不支持 支持并发插入的表级锁 SELECT,INSERT 读写操作频繁
MRG MYISAM 不支持 支持并发插入的表级锁 分段归档,数据仓库 全局查找过多的场景
Innodb 支持 支持MVCC的行级锁 事务处理
Archive 不支持 行级锁 日志记录,只支持insert,select 需要随机读取更新,删除
Ndb cluster 支持 行级锁 高可用性 大部份应用

为表中的字段选择合适的数据类型

  • 原则:当一个列可以选择多种数据类型时,应该优先考虑数字类型,其次是日期或二进制类型,最后是字符类型。对于相同级别的数据类型,应该优先选择占用空间小的数据类型

在进行数据库查询时,进行比较等操作,字符类型需要参照数据库排序规则

  • 整数类型:参照数据类型的长度进行选择
  • 实数类型:
    • FLOAT:4字节
    • DOUBLE:8字节
    • DECIMAL:每4个字节存储9个数字,小数点占1个字节
  • VARCHAR和CHAR类型存储方式跟存储引擎有很大关系
  • VARCHAR长度选择:使用最小的符合需求的长度
  • varchar(5)和varchar(200)存储’MySQL’字符串性能不同(查询时内存中使用固定宽度)
  • VARCHAR类型的存储特点:
    • varchar用于存储变长字符串,只占用必要的存储空间
    • 列的最大长度小于255则只占用一个额外字节用于记录字符串长度
    • 列的最大长度大于255则要占用两个额外字节用于记录字符串长度
  • VARCHAR的适用场景:
    • 字符串列的最大长度比平均长度大很多
    • 字符串列很少被更新(更新造成页分裂)
    • 使用了多字节字符集存储字符串
  • CHAR类型的存储特点:
    • CHAR类型是定长的
    • 字符串存储在CHAR类型的列中会删除末尾的空格
    • CHAR类型的最大宽度为255
  • CHAR类型的适用场景:
    • 适合存储所长度近似的值
    • 适合存储短字符串
    • 适合存储经常更新的字符串列(不会有存储碎片或造成页分裂)

如何存储日期类型数据

  • DATATIME类型
    • 以YYYY-MM-DD HH:MM:SS[.fraction]格式存储日期时间
    • datetime = YYYY-MM-DD HH:MM:SS
    • datetime(6)= YYYY-MM-DD HH:MM:SS.fraction
    • DATATIME类型与时区无关,占用8个字节的存储空间
    • 时间范围1000-01-01 00:00:00到9999-12-31 23:59:59
  • TIMESTAMP类型
    • 存储了由格林尼治时间1970年1月1日到当前时间的秒数以YYYY-MM-DD HH:MM:SS.[.fraction]的格式显示,占用4个字节
    • 时间范围1970-01-01 到 2038-01-19
    • timestamp类型显示依赖于所指定的时区
    • 在行的数据修改时可以自动修改timestamp列的值
  • date类型:
    • 占用的字节数比使用字符串、datetime、int存储要少,使用date类型只需要3个字节
    • 使用Date类型还可以利用日期时间函数进行日期之间的计算
    • 把日期部分存储为字符串(至少要8个字)
    • 使用int类型来存储(4个字节)
    • 使用datetime类型来存储(8个字节)
  • 存储日期时间数据的注意事项:
    • 不要使用字符串类型来存储日期时间数据
    • 日期时间类型通常比字符串占用的存储空间小
    • 日期时间类型在进行查找过滤时可以利用日期来进行对比
    • 日期时间类型还有着丰富的处理函数,可以方便的对时期类型进行日期计算
    • 使用Int存储日期时间不如使用Timestamp类型



第5章 MySQL高可用架构设计

MySQL复制功能概述

  • MySQL复制功能提供分担读负载
  • 为高可用、灾难恢复、备份提供更多选择
  • MySQL的复制功能通过二进制日志实现


MySQL复制解决了什么问题

  • 实现在不同服务器上的数据分布
    • 利用二进制日志增量进行,不需要太多的带宽
    • 但是使用基于行的复制在进行大批量的更改时会对带宽带来一定的压力,特别是跨IDC环境下进行复制,应该分批进行
  • 实现数据读取的负载均衡
    • 需要其它组件配合完成,利用DNS轮询的方式把程序的读连接到不同的备份数据库,使用LVS,haproxy这样的代理方式
    • 非共享架构,同样的数据分布在多台服务器上
  • 增强了数据安全性
    • 利用备库的备份来减少主库负载
    • 复制并不能代替备份
    • 方便进行数据库高可用架构的部署,避免MySQL单点失败
  • 实现数据库高可用和故障切换
  • 实现数据库在线升级


MySQL中的日志

  • MySQL服务层日志
    • 二进制日志:记录了所有对MySQL数据库的修改事件包括增删改查事件和对表结构的修改事件(已提交的,不包括回滚的)
    • 慢查询日志
    • 通用日志
  • MySQL存储引擎层日志
    • innodb:重做日志,回滚日志


二进制日志格式

基于段的格式

  • binlog_format=STATEMENT
  • 优点:




Reference




Remark

  1. 数据库三范式还需要加深理解。需要再深入学习
1
2
3
4
5
<font color=red></font>
![]()
<img src="" title="图片名称" alt="图片无法正常加载展示!" width="100%" height="100%" >
<img src="" width="70%">
****