mysql性能调优与架构设计笔记

时间:2022-06-01 19:41:48

1、mysql基本介绍

mysql支持多线程高并发的关系型数据库;

数据库存储引擎InnoDB、MyISAM;

mysql快速崛起的原因就是他是开源的;

性能一直是mysql自豪的一大特点;

2、mysql架构组成

麻雀虽小五脏俱全,mysql虽然简单但其内部结构并不简单;

mysql物理文件组成之日志文件:

错误日志error log这里记录mysql运行时严重的警告和错误,以及mysql启动和关闭的日志信息

二进制日志 binary log 记录mysql运行时所有的query和query执行的时间保存为二进制信息

查询日志 query log 记录所有query 包括select语句 体积较大开启后对性能有所影响

慢查询日志 slow query log 记录慢查询的日志信息

mysql物理文件组成之数据文件:

每一个数据库都会在定义好的数据目录下存在一个以数据库名字命名的文件夹,用来存放某个数据库各个表的数据信息;

不同的数据存储引擎有着不同的数据文件;

.frm拓展名的文件:不论是存储引擎,每个表都会有一个以表名.frm的文件,存放的是表结构的定义

.MYD拓展名的文件:MyISAM存储引擎专用,存放表数据,每一个表都会存在一个以表名.MYD的文件

.MYI拓展名的文件:MyISAM存储引擎专用,存放表索引数据,每个表都会存在一个以表名.MYI的文件

.ibd、.ibdata文件:InnoDB存储引擎专用,存放表数据和表索引,区别在于.ibd是独立存储每个表信息,每个表都有一个表名.idb文件这点和MyISAM一样,而ibdata文件是共享表空间存储数据信息;

mysql server系统架构之逻辑模块组成:

mysql可以看成是二层架构,第一层是sql layer,在mysql数据库系统处理底层数据之前的所有工作都在这一层完成,包括权限判断、sql解析、执行计划优化、query cache等工作,第二层是存储引擎层也就是数据存储实现的部份,有多种存储引擎组成;

虽然只有两个层但是每个层都有很多模块组成,也是相当的复杂;

sql layer层包含:(optimizer 优化程序)

初始化、核心Api、网络交互、client & server交互协议、用户模块、访问控制模块、

连接管理连接线程管理、query解析和转化、query cache、query优化器、表变更管理、

表维护、系统状态管理、表管理、日志记录、复制、存储引擎接口管理

mysql自带工具使用介绍:

mysql提供大量的客户端工具程序mysql、mysqladmin、mysqldump...

3、mysql存储引擎

mysql存储引擎概述:

MyISAM储存引擎是mysql默认的存储引擎;

Innodb存储引擎是第三方插件式存储引擎,是innobase公司开发,其最大特点是提供事务控制等功能;

MyISMA储存引擎简介:

MyISMA存储引擎的表在数据库中每一个表都被存放到三个以表名命名的物理文件中,分别是存放表结构定义的表名.frm文件、表数据表名.MYD文件、表索引表名.MYI文件;

MyISAM索引类型有三种:B-Tree、R-Tree、full-text,常用B-Tree类型索引;

MyISAM存储引擎有静态固定长度存储FIXED、动态可变长度存储DYNAMIC、压缩存储COMPRESS;

MyISAM储存引擎中某个表数据文件出错后不会影响到其他表或其他数据信息;

Innodb存储引擎简介:

mysql中除了MyISAM存储引擎之外适用作广泛就是Innodb存储引擎,他和MyISAM一样遵循开源license协议;

Innodb的优点就是提供了事务控制功能;

Innodb提升了MyISAM锁的机制,实现了行锁功能;

Innodb的数据存储和MyISAM也不一样,虽然也有表结构定义信息表名.frm文件,表数据和表索引是在一个文件里面存储.ibd单独的存储、.ibdata共享存储;

Innodb的物理结构可以分成两大类:

数据文件(存放表数据和表索引数据).ibd单独的存储、.ibdata共享存储两种类型;

日志文件:请不要全部删除Innodb的日志文件这样会让数据库crash(崩溃),或提示数据丢失;

Memory存储引擎:

Memory存储引擎就是把数据存储在内存里面的一种引擎;

Memory存储引擎不会把数据存储在磁盘,存入磁盘的只是表名.frm结构,因此如果数据库crash或者宕机都会导致数据丢失;

小结:多存储引擎是mysql有别于其他数据库的一大特性;后续对常用的存储引擎会进行详情介绍;

4、mysql安全管理

对企业来说数据库保存的数据的安全性是非常重要的;

数据失去了安全性就等于失去了一切;

数据库系统安全相关因素:

外围网络安全:mysql是基于网路环境的,而网络本身就存在一种入侵的威胁;要从最外层预防;

尽量让mysql存在有保护的局域网环境中;

主机防御:外围网络预防得到了保护,那么还是会存在入侵的可能,那就是局域网入侵;

主要是阻止没有授权的设备连接mysql;

入侵数据库危害盗取数据、删除数据、制造漏洞;

数据库防御:通过第二道防线我们可以预防一部分威胁,可是允许使用主机登录的设备是否

完全拥有权限呢?是否是可信任的对象呢?

数据库防线是mysql自身系统的访问控制授权模块,这道防线是mysql入侵的最后一道防线了;

设置登录用户名和密码和端口号并并设置权限;

代码防御:sql语句相关安全因素、sql注入攻击、程序代码相关安全因素

DDL、DML、DCL

数据库定义语言(CREATE ALTER DROP TRUNCATE)

数据库操作语言(SELECT INSERT UPDATE DELETE EXPLAN)

数据库控制语言(COMMIT ROLLBACK)

mysql访问控制实现原理:

mysql访问控制其实有2部分组成:一是用户模块管理、一是访问控制模块管理(权限);

用户模块决定是否能进入,访问控制模块(权限)决定能有哪些操作;

例如:客户端请求(提供host,用户名,密码)-->用户模块验证(通过mysql.user表验证)-->

客户端请求query(DML、DDL)-->解析query执行权限-->权限匹配查找(grant tables中查找)

-->发往后端继续执行

mysql访问授权策略:

不是每个用户的权限都一样无限大;

每个用户的权限做到越小越好,满足使用就好;

首先了解来访主机、了解用户需求、最后为工作分类,这样确保绝对必要拥有者拥有grant(准许)权限;

备注:安全无小事,数据是一个企业的财富;

5、mysql数据的备份与恢复

数据库备份使用的场景:

数据丢失应用场景:人为误操作、软件bug、硬件故障、安全漏洞

非数据丢失场景:特殊场景下数据恢复、开发测试数据库搭建、数据库或数据迁移

备注:数据库数据备份解决问题不是万能的;

6、影响mysql server性能的相关因素

大多都认为数据库应用系统的性能瓶颈是数据库管理软件和数据库主机自身造成的,其实不然;

下面以mysql数据库web场景为例来分析影响性能的瓶颈;

商业需求对性能的影响:

不是所有功能都能实现,有些不合理的功能反而最后成了累赘,消耗资源;

不合理的需求造成资源投入产出比过低;

无用功能堆积使系统过度复杂影响整体性能;(无用的功能大多不会下线,因为考虑风险,所以系统越来越庞大复杂,不仅维护困难,系统性能也越来越差)

系统架构及实现对性能的影响:

一个web应用自然离不开应用程序(web application)和web应用程序服务器(web server),web server我们控制调优的不多都是很成熟的产品,web application我们可以优化很多方面;

以下几类数据不适合存放到数据库中:

二进制多媒体数据(消耗内存、消耗cpu);

流水队列数据(不断的进行insert update delete因为每次操作都会写入日志文件影响性能);

超大文本数据(占用空间浪费资源)

是否合理利用应用层cache机制:mysql memory存储引擎

通过cache机制成功的案例很多很多,可是失败的案例也很多;

下面整理哪些可以使用cache机制:

系统各种配置和规则的数据;

活跃用户的基本信息(缓存用户的基本信息可以大大提升性能);

时间段的统计数据;

访问平凡更新较少的数据;

过度依赖数据库sql语句的功能造成数据库操作效率低下:

尽量不要在循环中多次执行sql,有时可以使用2个sql,这样不占用IO和解析资源;

如果一条sql查询的列不是全部使用时请拆分成2个sql,减少不适用列的查询;

避免重复执行相同的sql浪费资源(这里可能和上面两条像违背,分不同逻辑考虑取舍)

架构设计不当带来性能问题和资源浪费问题:

cache命中率低,增加数据库的访问压力,浪费cache资源利用率;

过度依赖面向对象,对可拓展性的过度追求;

对数据库的过度依赖,一些不符合存入数据库的应该存入文件系统中;

过度的在乎用户体验,比如不用实时更新的数据实时更新了浪费资源;

query语句对性能的影响:

当mysql的连接线程接收到client请求的sql时,会经过解析和分析,然后通过执行计划调用存储过程接口,最后把数据返回给client显示;

执行sql主要是IO消耗和cpu消耗(这里可以通过explain进行测试);

备注:有时间测试下两个表先连接查询和先查询一个表信息在和另一个表连接分析哪个好?

schema(方案)的设计对系统性能的影响:

数据库设计对性能的提升;

适当的使用好范式是对设计最大的调优;

硬件环境对性能的影响:

考虑并发访问比较频繁的时候要考虑服务器IO和CPU处理能力;

7、mysql数据库锁定机制

为了保证数据的完整性任何一种数据库都有锁定的机制;

一个数据库锁定技术的优劣直接影响数据库高并发处理和性能;

mysql常用存储引擎Innodb、MyISAM

mysql锁定机制简介:

行级锁定:

行级锁定最大的特点就是对象的颗粒度很小,是最常用的一种形式;

由于锁定颗粒下取锁和锁定处理的事情比较多,耗内存,也最容易发生死锁;

表级锁定:

表级锁定与行级锁定的特点正好相反,是锁定mysql存储引擎中最大的颗粒;

表锁定逻辑简单、处理快、耗能小、不容易死锁;

页级锁定:

页级锁定是mysql一个比较独特的锁定机制,锁定介于行锁和表锁之间;

页级锁定和行级锁定一样,很容易被死锁;

备注:行级锁定不是mysql自己的锁定机制,而是第三方Innodb存储引擎的锁定机制;

Innodb如果产生死锁时会通过检测死锁机制来判断要回滚那个事务sql,这里会根据影响数据的大小来判断,让影响数据大的事务sql执行成功,回滚影响小的事务sql;或者通过死锁机制过期时间来回滚事务sql;

Innodb行级锁的优点:

在很多线程请求不同记录时减少冲突;

事务回滚时减少改变的数据;

使长时间对单独的一行记录加锁成为可能;

Innodb行锁的缺点:

比表级别锁和页级别锁消耗更多的内存;

合理的利用锁机制优化mysql:

MyISAM的表锁优化建议:

MyISAM的表锁比行锁和页锁减小了资源,但是一定程度上影响了并发的性能,

因此优化表锁的建议就是如何提高并发的性能;

缩短锁定时间;

唯一的办法让sql执行时间尽可能的短;

庞大复杂的sql建议分成多个小sql分布式执行;

尽可能的建立高效的索引和字段类型限制;

分离能并行的操作;

合理利用读写优先级;

Innodb行锁的优化建议:

Innodb的行锁机制虽然比MyISAM的表锁机制消耗很大的资源但是高并发却远远超于后者;

Innodb的行锁也有瓶颈的一面:

查询尽量使用索引提高查询速度;

合理的设计索引;

查询的范围不应过大;

系统锁定情况查询:

表锁定情况查询:

SHOW STATUS LIKE '%table%';

Table_locks_immediate 表锁定的次数

Table_locks_waited    表锁定等待的次数

Table_locks_waited如果数值变大了说明表争用比较严重,需要优化;

Innodb行锁的情况查询:

SHOW STATUS LIKE '%innodb_row_lock%';

Innodb_row_lock_current_waits   //当前正在等待锁定的数量

Innodb_row_lock_time    //从系统启动到现在锁定总时间长度

Innodb_row_lock_time_avg    //每次等待所花费的平均时间

Innodb_row_lock_time_max    //某次等待最长的时间

Innodb_row_lock_waits   //从系统启动到现在请求的次数

上述分析:重要的是1 3 5这几个值

Innodb存储引擎的整体性能要高于MyISAM存储引擎

8、mysql数据库中query的优化

mysql query optimizer:

mysql query optimizer 是query查询优化器模块,提供最优的执行计划;

query语句优化的思路和原则:

优化更需要优化的query;

定位优化对象的性能瓶颈;//是IO还是CPU还是内存

明确的优化目标;

多使用show profiles;

从explain sql入手; //因为它可以展示执行计划详细信息

最可能的在索引中排序;

只取出自己需要的columns;

使用最有效的过滤条件;

尽可能避免复杂的join和子查询;

优化更需要优化的query:

两个query每小时执行的IO数是一样的,一个是每小时执行10000次每次消耗20个IO,

一个是每小时执行10次每次消耗20000个IO那么试问该优化哪个query呢?

解答:第一个query把IO从20降到18就减少了2个,那么就2*10000 = 20000个IO

第二个query如果能减少20000个IO那么20000/10 = 2000个IO那么每次需减少2000个IO

因此我们觉得那个更好优化呢,哪个能减少更少的IO呢,第一个query;

执行高并发的query比执行低并发的危险性要高的多,高并发的query很容易让系统crash掉,

等我们重新启动后系统负荷就会直线飙升接近crash,让我们都不能查询问题出现在哪里,

而低并发的query虽然也产生负荷至少还在可控范围内;

join时的原则就是‘小结果集驱动大结果集的’:

A表1000数据,B表10万条数据 SELECT A.*, B.name FROM A LEFT JOIN B ON A.id=B.a_id

//这里就是以A表作为驱动表循环连接B表信息;减少了循环次数;B表示被驱动表;

explain sql语句详细分析:

注意key_len的值,越小越好;

//也就是说往往一个where条件可以查询到的就不要再用第二个没有意义的条件了哦,因为消耗内存;

mysql中索引的限制:

MyISAM存储引擎的索引键值长度总和不能超过1000字节;

mysql目前不支持函数索引;

mysql查询条件!= 、<>的时候不能使用索引;

使用like查询 like'%abc'这样无法使用索引;

join的原理和优化思路:

SELECT A.*

FROM USER_GROUP A LEFT JOIN GROUP_MESSAGE B ON A.group_id = B.group_id

LEFT JOIN GROUP_MESSAGE_CONTENT C ON B.id = C.message_id

WHERE A.user_id = 1;

//这里是把USER_GROUP表作为驱动表, 先A表通过索引查询出group_id集合作为驱动表,

//对GROUP_MESSAGE表进行循环查询出id,最后在通过索引message_id查询出最终结果集合;

尽可能的减少join语句的循环次数;

连接的字段必须建索引;

GROUP BY/ ORDER BY尽量使用索引;

9、mysql数据库schema(图标)的设计和调优

高效的模型设计:

首先考虑符合第一第二第三范式;

适当沉余让query尽量减少join;

举例:user表,message表中可以添加个author_name字段;

大字段垂直分隔;

blog表中有个content字段text类型可以分隔成blog_detail表;

统计表准实时更新;

统计的数据不建议实时更新,这里就是商业需求影响性能,可以使用定时实时更新;

合适的数据类型:

尽量使用小的数据类型来减少磁盘的空间;

通过合适的数据类型进行数值比较;

规范的对象命名:

数据库和表命名应尽可能的和所属产品描述相符合;

字段名也应和该列信息描述相符合;

索引名称尽量包含字段名称或字段缩写;

备注:数据库性能的提升不是优化出来的而是设计出来的;

10、mysql性能优化

mysql安装优化:

安装适合的数据库版本;

mysql日志性能优化:

错误日志(error log);

更新日志(update log);

二进制日志(binlog);

查询日志(query log);

慢查询日志(slow query sql);

mysql query cache的优化:

mysql query cache产生可以让mysql性能产生质的飞越;

mysql server的其他优化:

网络允许的最大连接数;max_connections处理并发能力

用户允许的组大连接数;max_user_connextions针对于单个用户的连接限制;

网络包传输中,传输信息之前net_buffer的初始化大小;net_buffer_length;

网络传输中一次传输信息的最大值;max_allowed_packet;

mysql连接等待中的最大数量;back_log;

11、常用存储引擎优化

mysql中MyISAM存储引擎优化;

mysql中Innodb存储引擎优化;

12、mysql可拓展设计的基本原则

13、可拓展性设计之mysql replication(复制)

14、可拓展性设计之数据切分

何为数据切割:

按照不同的表来切分到不同的数据库上这个是垂直(纵向)切割模式;

把同一个表按照某种逻辑关系分别拆分存放到不同的数据库上这个是水平切割模式;

备注:垂直分隔的特点就是简单,低耦合的表可以进行垂直分隔;

如果我们做了垂直分隔后还任然不能提高性能时我们还的进行水平分隔;

数据的垂直分隔:

数据库中的表都是有多个功能模块组成,每个功能模块之前的耦合度越小越容易进行垂直分隔;

垂直分隔优点:

数据库拆分简单明了,拆分规则明确;

应用程序模块清晰明确,整合容易;

数据维护方便容易定位;

垂直分隔缺点:

部分表关联无法在数据库中完成;

切分成一定程度之后拓展性降低;

数据水平分隔:

数据的水平分隔是高并发查询的表通过某个字段的规则吧数据分别存放不同的表中进行查询,

这样每张表的数据集合就没有之前一张表大,从而来提示查询速度,常见的方案是通过userid

对5取模然后分别存放到5个表中,显示查询则通过userid对5取模,余数就知道此userid存在哪里;

备注:通过数据分隔技术将一个大的数据mysql server分隔成多个小数据的mysql server,这样提高了

查询和写入性能, 最佳方案是先进行垂直分隔再进行水平分隔;

15、可拓展性设置cache和search的利用

分布式缓存cache解决方案memcached;

利用search实现高效的全文索引;

备注:数据库只是存储数据的工具,他的特点就是持久化,除了数据库我们还有很多其他方式的数据存储;

16、mysql cluster(集群)

mysql cluster是一个基于NDB cluster存储引擎的完整的分布式数据库系统;