RDS | Oralce | MySQL我爱编程编程小技巧

mysql笔记(转)

2018-07-25  本文已影响229人  信仰与初衷

今天看到一位朋友写的mysql笔记总结,觉得写的很详细很用心,这里转载一下,供大家参考下,也希望大家能关注他
原文地址: https://www.jianshu.com/p/47664afa249e

一、MySQL架构与历史

A.并发控制

1.共享锁(shared lock,读锁):共享的,相互不阻塞的

2.排他锁(exclusive lock,写锁):排他的,一个写锁会阻塞其他的写锁和读锁

B.事务

1.事务ACID

2.四种隔离级别

3.死锁:指两个或多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环的现象

4.事务日志:存储引擎在修改表的数据时只需要修改其内存拷贝,再把该修改行为记录到持久在硬盘上的事务日志中,而不用每次都将修改的数据本身持久到磁盘。事务日志持久以后,内存中被修改的数据在后台可以慢慢地刷回到磁盘,称为预写式日志(Write-Ahead Logging)

C.多版本并发控制

1.多版本并发控制(MVCC)是行级锁的一个变种,但是它在很多情况下避免了加锁操作,因此开销更低。虽然实现机制有所不同,但大都实现了非阻塞的读操作,写操作也只锁定必要的行

2.MVCC的实现,是通过保存数据在某个时间点的快照来实现的,有乐观和悲观两种,只在REPEATABLE READ和READ COMMITTED两个隔离级别下工作

D.MySQL的存储引擎

1.MySQL的.frm文件保存表的定义,SHOW TABLE STATUS显示表的相关信息

2.除非有非常特别的原因需要使用其他的存储引擎,否则应该优先考虑InnoDB引擎

3.不要轻易相信MyISAM比InnoDB快之类的经验之谈,这个结论并不是绝对的

二、MySQL基准测试

A.为什么需要基准测试

1.基准测试可以观察系统在不同压力下的行为,评估系统的容量,掌握哪些是重要的变化,或者观察系统如何处理不同的数据

B.基准测试的策略

1.两种主要的策略:

2.测试何种指标:

C.基准测试方法

1.需要避免的一些常见错误:

2.应该建立将参数和结果文档化的规范,每一轮测试都必须进行详细记录

3.基准测试应该运行足够长的时间,需要在稳定状态下测试并观察

4.在执行基准测试时,需要尽可能多地收集被测试系统的信息

5.自动化基准测试可以防止测试人员偶尔遗漏某些步骤,或者误操作,另外也有助于归档整个测试过程,可以选择shell、php、perl等,要尽可能使所有测试过程都自动化,包括装载数据、系统预热、执行测试、记录结果等

D.基准测试工具

1.集成式测试工具:

2.单组件式测试工具

三、服务器性能剖析

A.性能优化简介

1.性能,为完成某件任务所需要的时间度量,性能即响应时间,这是非常重要的原则

2.如果目标是降低响应时间,就需要理解为什么服务器执行查询需要这么多时间,然后去减少或者消除那些对获得查询结果来说不必要的工作。无法测量就无法有效地优化

3.性能剖析(profiling)是测量和分析时间花费在哪里的主要方法,一般有两个步骤:测量任务所花费的时间,对结果进行统计和排序

B.对应用程序进行性能剖析

1.性能瓶颈可能的影响因素:

2.PHP性能剖析工具:New Relic、xhprof、Ifp

C.剖析MySQL查询

1.剖析服务器负载

2.剖析单条查询:

D.诊断间歇性问题

1.尽量不要用试错的方式来解决问题,如果一时无法定位,可能是测量的方式不正确,或者测量的点选择有误,或者使用的工具不合适

2.确定单条查询问题还是服务器问题

3.捕获诊断数据

E.其他剖析工具

1.使用USER_STATISTICS表

2.使用strace,可以调查系统调用的情况

四、Schema与数据类型优化

A.选择优化的数据类型

1.数据类型的选择原则:

2.应该尽量只在对小数进行精确计算时才使用DECIMAL,使用int类型通过程序控制单位效果更好

3.使用VARCHAR合适的情况:字符串列的最大长度比平均长度大很多;列的更新很少,所以碎片不是问题;使用了像UTF-8这样复杂的字符集,每个字符都使用不同的字节数进行存储

4.CHAR适合存储很短的字符串,或者所有值都接近同一个长度;不容易产生碎片,在存储空间上更有效率

5.通常应该尽量使用TIMESTAMP,它比DATETIME空间效率更高

B.MySQL schema设计中的陷阱

1.不好的设计:

C.范式和反范式

1.范式的优点:

2.范式化设计的缺点是通常需要关联

3.反范式的优点:避免关联,避免了随机I/O,能使用更有效的索引策略

D.缓存表和汇总表

1.有时提升性能最好的方法是同一张表中保存衍生的冗余数据,有时也需要创建一张完全独立的汇总表或缓存表

2.物化视图,MySQL并不原生支持,Flexviews

3.如果应用在表中保存计数器,则在更新计数器时可能踫到并发问题,创建一张独立的表存储计数器,可以帮助避免缓存失效

E.加快ALTER TABLE操作的速度

1.两种方式:

2.快速创建MyISAM索引,先禁用索引,导入数据,然后重新启用索引

五、创建高性能的索引

A.索引基础

1.索引可以包含一个或多个列的值,如果索引包含多个列,那么列的顺序也十分重要,因为MySQL只能高效地使用索引的最左前缀列

2.ORM工具能够产生符合逻辑的、合法的查询,除非只是生成非常基本的查询,否则它很难生成适合索引的查询

3.在MySQL中,索引是在存储引擎层而不是服务器层实现的,所以,并没有统一的索引标准:不同存储引擎的索引的工作方式并不一样,也不是所有的存储引擎都支持所有类型的索引

4.B-Tree意味着所有的值都是按顺序存储的,并且每一个叶子页到根的距离相同,能够加快访问数据的速度,从索引的根节点开始进行搜索,适用于全键值、键值范围或键前缀查找

image.png

5.B-Tree索引的限制:

6.哈希索引(hash index)基于哈希表实现,只有精确匹配索引所有列的查询才有效,只有Memory引擎显式支持哈希索引

7.哈希索引的限制:

8.空间数据索引(R-Tree),MyISAM表支持空间索引,可以用作地理数据存储,开源数据库系统中对GIS的解决方案做得比较好的是PostgreSQL的PostGIS

9.全文索引,适用于MATCH AGAINST操作,而不是普通的WHERE条件操作

B.索引的优点

1.三个优点:

2.索引三星系统:

C.高性能的索引策略

1.独立的列:如果查询中的列不是独立的,则MySQL不会使用索引。“独立的列”是指索引列不能是表达式的一部分,也不能是函数的参数

2.前缀索引和索引选择性

3.选择合适的索引列顺序

4.聚簇索引:并不是一种单独的索引类型,而是一种数据存储方式

5.覆盖索引:如果一个索引包含(或者说覆盖)所有需要查询的字段的值,就称为覆盖索引

6.如果EXPLAIN出来的type列的值为“index”,则说明MySQL使用了索引扫描来做排序

7.压缩(前缀)索引,默认只压缩字符串,减少索引大小,对于CPU密集型应用,因为扫描需要随机查找,压缩索引在MyISAM上要慢好几倍

8.重复索引是指在相同的列上按照相同的顺序创建的相同类型的索引,应该避免这样创建重复索引

9.索引可以让查询锁定更少的行

D.维护索引和表

1.CHECK TABLE检查表是否损坏,ALTER TABLE innodb_tb1 ENGINE=INNODB;修复表

2.records_in_range()通过向存储引擎传入两个边界值获取在这个范围大概有多少条记录,对于innodb不精确

3.info()返回各种类型的数据,包括索引的基数

4.可以使用SHOW INDEX FROM命令来查看索引的基数

5.B-Tree索引可能会碎片化,这会降低查询的效率

六、查询性能优化

A.为什么查询速度会慢

1.如果要优化查询,实际上要优化其子任务,要么消除其中一些子任务,要么减少子任务的执行次数,要么让子任务运行得更快

2.查询的生命周期大致可以按照顺序来看:从客户端,到服务器,然后在服务器上进行解析,生成执行计划,执行,并返回结果给客户端

B.慢查询基础:优化数据访问

1.两个分析步骤:

2.是否向数据库请求了不需要的数据

3.MySQL是否在扫描额外的记录

C.重构查询的方式

1.MySQL从设计上让连接和断开连接都很轻量级,在返回一个小的查询结果方面很高效

2.切分查询,将大查询切分成小查询,每个查询功能完全一样,只完成一小部分,每次只返回一小部分查询结果,可以避免锁住很多数据、占满事务日志、耗尽系统资源、阻塞很多小的但重要的查询

3.分解关联查询优势:

4.分解关联查询的场景:

D.查询执行的基础

1.查询执行路径

2.MySQL客户端和服务器之间的通信协议是“半双工”的,无法将一个消息切成小块独立来发送,没法进行流量控制,一旦一端开始发生消息,另一端要接收完整个消息才能响应它

3.MySQL通常需要等所有的数据都已经发送给客户端才能释放这条查询所占用的资源,所以接收全部结果并缓存通常可以减少服务器的压力

4.查询状态,SHOW FULL PROCESSLIST命令查看:

5.语法解析器和预处理,通过关键字将SQL语句进行解析,并生成一棵对应的“解析树”,解析器将使用MySQL语法规则验证和解析查询,预处理器则根据一些MySQL规则进一步检查解析树是否合法

6.查询优化器,找到最好的执行计划,使用基本成本的优化器,将尝试预测一个查询使用某种执行计划时的成本,并选择其中成本最小的一个,使用SHOW STATUS LIKE 'Last_query_cost';查看需要多少个数据页的随机查找

7.导致MySQL查询优化器选择错误的原因:

8.MySQL能处理的优化类型:

9.在服务器层有查询优化器,却没有保存数据和索引的统计信息,统计信息由存储引擎实现,不同的存储引擎可能会存储不同的统计信息

10.在MySQL中,每一个查询,每一个片段(包括子查询,甚至基于单表的SELECT)都可能是关联

11.对于UNION查询,MySQL先将一系列的单个查询结果放到一个临时表中,然后再重新读出临时表数据来完成UNION查询

12.MySQL对任何关联都执行“嵌套循环关联”操作,即MySQL先在一个表中循环取出单条数据,然后再嵌套到下一个表中寻找匹配的行,依次下去,直到找到所有表中匹配的行为止

13.全外连接就无法通过嵌套循环和回溯的方式完成,当发现关联表中没有找到任何匹配行的时候,则可能是因为关联恰好从一个没有任何匹配的表开始,MySQL不支持全外连接

14.关联查询优化器,会尝试在所有的关联顺序中选择一个成本最小的来生成执行计划树,如果可能,优化器会遍历每一个表然后逐个做嵌套循环计算每一棵可能的执行树的成本,最后返回一个最优的执行计划

15.如果有超过n个表的关联,那么需要检查n的阶乘关联顺序,称为“搜索空间”,搜索空间的增长速度非常快

16.无论如何排序都是一个成本很高的操作,所以从性能角度考虑,应尽可能避免排序或者尽可能避免对大量数据进行排序

17.当不能使用索引生成排序结果的时候,MySQL需要自己进行排序,如果数据量小则在内存中进行,如果数据量大则需要使用磁盘,MySQL将这个过程称为文件排序(filesort),即使完全是内存排序不需要任何磁盘文件时也是如此

E.MySQL查询优化器的局限性

1.关联子查询:MySQL的子查询实现得非常糟糕,最糟糕的一类查询是WHERE条件中包含IN()的子查询语句,使用GROUP_CONCAT()在IN()中构造一个由逗号分隔的列表,或者使用EXISTS()来改写

2.UNION的限制:有时,MySQL无法将限制条件从外层“下推”到内层,这使得原本能够限制部分返回结果的条件无法应用到内层查询的优化上

3.MySQL无法利用多核特性来并行执行查询

4.MySQL不支持哈希关联,MariaDB已经实现了哈希关联

5.MySQL不支持松散索引扫描,5.0后版本在分组查询中需要找到分组的最大值和最小值时可以使用松散索引扫描

6.对于MIN()和MAX()查询,MySQL的优化做得并不好

F.查询优化器的提示(hint)

1.HIGH_PRIORITY和LOW_PRIORITY,当多个语句同时访问某一个表的时候,哪些语句的优先级相对高些、哪些语句的优先级相对低些

2.DELAYED,对INSERT和REPLACE有效,会将使用该提示的语句立即返回给客户端,并将插入的行数据放入到缓冲区,然后在表空闲时批量将数据写入,并不是所有的存储引擎都支持,并且该提示会导致函数LAST_INSERT_ID()无法正常工作

3.STRAIGHT_JOIN,可以放置在SELECT语句的SELECT关键字之后,也可以放置在任何两个关联表的名字之间。第一个用法是让查询中所有的表按照在语句中出现的顺序进行关联,第二个用法则是固定其前后两个表的关联顺序

4.SQL_SMALL_RESULT和SQL_BIG_RESULT,只对SELECT语句有效,它们告诉优化器对GROUP BY或者DISTINCT查询如何使用临时表及排序

5.SQL_BUFFER_RESULT,告诉优化器将查询结果放入到一个临时表,然后尽可能快地释放表锁

6.SQL_CACHE和SQL_NO_CACHE,告诉MySQL这个结果集是否应该缓存在查询缓存中

7.SQL_CALC_FOUND_ROWS,会计算除去LIMIT子句后这个查询要返回的结果集的总数,而实际上只返回LIMIT要求的结果集,可以通过函数FOUND_ROW()获得这个值

8.FOR UPDATE和LOCK IN SHARE MODE,主要控制SELECT语句的锁机制,但只对实现了行级锁的存储引擎有效,仅InnoDB支持

9.USE INDEX、IGNORE INDEX和FORCE INDEX,告诉优化器使用或者不使用哪些索引来查询记录

10.MySQL5.0后新增的用来控制优化器行为的参数:

G.优化特定类型的查询

1.优化COUNT()查询

2.优化关联查询

3.优化子查询:尽可能使用关联查询代替,如果使用MySQL5.6以上或MariaDB则可以忽略这个建议

4.优化GROUP BY和DISTINCT

5.优化LIMIT分页

6.优化UNION查询

七、MySQL高级特性

A.分区表

1.对用户来说,分区表是一个独立的逻辑表,但是底层由多个物理子表组成,实际上是对一组底层表的句柄对象(Handler Object)的封装

2.适用场景:

3.使用限制:

4.使用分区表

5.保证大数据量的可扩展性两个策略:

6.分区策略的问题:

7.查询优化

B.视图

1.视图本身是一个虚拟表,不存放任何数据,返回的数据是MySQL从其他表中生成的

2.MySQL使用两种算法:合并算法(MERGE)和临时表算法(TEMPTABLE),会尽可能地使用合并算法

3.如果视图中包含GROUP BY、DISTINCT、任何聚合函数、UNION、子查询等,只要无法在原表记录和视图记录中建立一一映射的场景中,MySQL都将使用临时表算法来实现视图

4.可更新视图(updatable view)是指可以通过更新这个视图来更新视图涉及的相关表,CHECK OPTION表示任何通过视图更新的行,都必须符合视图本身的WHERE条件定义

5.在重构schema的时候可以使用视图,使得在修改视图底层表结构的时候,应用代码还可能继续不报错运行

6.MySQL中不支持物化视图(指将视图结果数据存放在一个可以查看的表中,并定期从原始表中刷新数据到这个表中)

7.不会保存视图定义的原始SQL语句

C.外键约束

1.使用外键是有成本的,通常要求每次在修改数据时都要在另外一张表中多执行一次查找操作

2.如果想确保两个相关表始终有一致的数据,那么使用外键比在应用程序中检查一致性的性能要高得多,在相关数据的删除和更新上,也比在应用中维护要更高效

3.外键会带来很大的额外消耗

D.在MySQL内部存储代码

1.MySQL允许通过触发器、存储过程、函数的形式来存储代码,从5.1开始还可以在定时任务中存放代码,这个定时任务也被称为“事件”。存储过程和存储函数都被统称为“存储程序”

2.存储代码的优点:

3.存储代码的缺点:

4.存储过程和函数的限制:

5.触发器:可以让你在执行INSERT、UPDATE或者DELETE的时候,执行一些特定的操作,可以在MySQL中指定是在SQL语句执行前触发还是在执行后触发,可以使用触发器实现一些强制限制,或者某些业务逻辑,否则,就需要在应用程序中实现这些逻辑

6.触发器的注意和限制:

7.触发器的用处:

8.事件:类似于Linux的定时任务,指定MySQL在某个时候执行一段SQL代码,或者每隔一个时间间隔执行一段SQL代码

E.游标

1.MySQL在服务器端提供提供只读的、单向的游标,而且只能在存储过程或者更底层的客户端API中使用,指向的对象都是存储在临时表中而不是实际查询到的数据,所以总是只读的

2.会带来额外的性能开销

3.不支持客户端的游标

F.绑定变量

1.当创建一个绑定变量SQL时,客户端向服务器发送了一个SQL语句的原型。服务器端收到这个SQL语句框架后,解析并存储这个SQL语句的部分执行计划,返回给客户端一个SQL语句处理句柄。以后每次执行这类查询,客户端都指定使用这个句柄

2.可以更高效地执行大量的重复语句:

3.绑定变量相对也更安全。无须在应用程序中处理转义,一则更简单了,二则也大大减少了SQL注入和攻击的风险

4.最主要的用途就是在存储过程中使用,构建并执行“动态”的SQL语句

5.绑定变量的限制:

G.用户自定义函数

1.用户自定义函数(UDF)必须事先编译好并动态链接到服务器上,这种平台相关性使得UDF在很多方面都很强大,但一个错误也很可能让服务器直接崩溃,甚至扰乱服务器的内存或者数据

H.插件

1.插件可以在MySQL中新增启动选项和状态值,还可以新增INFORMATION_SCHEMA表,或者在MySQL的后台执行任务等等

2.在5.1后支持的插件接口:

I.字符集和校对

1.字符集是一种从二进制编码到某类字符符号的映射,可以参考如何使用一个字节来表示英文字母。“校对”是指一组用于某个字符集的排序规则

2.每种字符集都可能有多种校对规则,并且都有一个默认的校对规则,每个校对规则都是针对某个特定的字符集的,和其他的字符集没有关系

3.MySQL有很多的选项用于控制字符集,这些选项和字符集很容易混淆,只有基于字符的值才真正的“有”字符集的概念

4.MySQL的两类设置:创建对象时的默认设置、服务器和客户端通信时的设置

5.如果比较的两个字符串的字符集不同,MySQL会先将其转成同一个字符集再进行比较

6.一些需要注意的地方:

7.某些字符集和校对规则可能会需要更多的CPU操作,可能会消耗更多的内存和存储空间,甚至还会影响索引的正常使用

J.全文索引

1.MyISAM的全文索引作用对象是一个“全文集合”,这可能是某个数据表的一列,也可能是多个列

2.可以根据WHERE子句中的MATCH AGAINST来区分查询是否使用全文索引

3.在使用全文索引进行排序的时候,MySQL无法再使用索引排序,如果不想使用文件排序的话,就不要在查询中使用ORDER BY子句

4.在布尔搜索中,用户可以在查询中自定义某个被搜索的词语的相关性,可能通过一些前缀修饰符来定制搜索

5.全文索引在INSERT、UPDATE、DELETE中的操作代价很大

6.全文索引会影响索引选择、WHERE子句、ORDER BY等:

7.全文索引的配置和优化:

K.分布式(XA)事务

1.XA事务中需要有一个事务协调器来保证所有的事务参与者都完成了准备工作。如果协调器收到所有的参与者都准备好的消息,就会告诉所有的事务可以提交了,MySQL在这个XA事务过程中扮演一个参与者的角色,而不是协调者

2.因为通信延迟和参与者本身可能失败,所以外部XA事务比内部消耗会更大

L.查询缓存

1.MySQL查询缓存保存查询返回的完整结果,当查询命中该缓存,MySQL会立刻返回结果,跳过了解析、优化和执行阶段

2.MySQL判断缓存命中的方法很简单:缓存放在一个引用表中,通过一个哈希值引用,这个哈希值包括了如下因素,即查询本身、当前要查询的数据库、客户端协议的版本等一些其他可能会影响返回结果的信息

3.当判断缓存是否命中时,MySQL不会解析、“正规化”或者参数化查询语句,而是直接使用SQL语句和客户端发送过来的其他原始信息。任何字符上的不同,例如空格、注释——都会导致缓存的不命中

4.当查询语句中有一些不确定的数据时,则不会被缓存,例如包含函数NOW()或者CURRENT_DATE()的查询不会被缓存,只要包含任何用户自定义函数、存储函数、用户变量、临时表、mysql库中的系统表,或者任何包含列级别权限的表,都不会被缓存

5.打开查询缓存对读和写操作都会带来额外的消耗:

6.对于需要消耗大量资源的查询通常都是非常适合缓存的

7.缓存未命中:

8.缓存参数配置:

9.InnoDB和查询缓存

10.通用查询缓存优化:

八、优化服务器设置

A.MySQL配置的工作原理

1.任何打算长期使用的设置都应该写到全局配置文件,而不是在命令行特别指定

2.常用变量和动态修改它们的效果:

3.对于连接级别的设置,不要轻易地在全局级别增加它们的值,除非确认这样做是对的

4.设置变量时请小心,并不是值越大就越好,而且如果设置的值太高,可能更容易导致问题:可能会由于内存不足导致服务器内存交换,或者超过地址空间

5.不要期望通过建立一套基准测试方案,然后不断迭代地验证对配置项的修改来找到最佳配置方案,而要把时间花在检查备份、监控执行计划的变动之类的事情上,可能会更有意义

B.什么不该做

1.不要根据一些“比率”来调优:例如缓存命中率跟缓存是否过大或过小没有关系2.不要使用调优脚本

3.不要相信很流行的内存消耗公式

C.创建MySQL配置文件

1.MySQL编译的默认设置并不都是靠谱的,虽然其中大部分都比较合适

2.从一个比默认值大一点但不是大得很离谱的安全值开始是比较好的,MySQL的内存利用率并不总是可以预测的:它可能依赖很多的因素,例如查询的复杂性和并发性

3.配置服务器的首选途径:了解它内部做了什么,以及参数之间如何相互影响,然后再决定

4.open_files_limit,在Linux系统上设置得尽可能大,如果参数不够大,将会踫到24号错误“打开的文件太多(too many open files)”

5.每隔60秒查看状态变量的增量变化:mysqladmin extended-status ri60

D.配置内存使用

1.配置MySQL正确地使用内存量对高性能是至关重要的,内存消耗分为两类:可以控制的内存和不可以控制的内存

2.配置内存:

3.MySQL保持一个连接(线程)只需要少量的内存,它还需要一个基本量的内存来执行任何给定查询,需要为高峰时期执行的大量查询预留好足够的内存,否则,查询执行可能因为缺乏内存而导致执行效率不佳或执行失败

4.跟查询一样,操作系统也需要保留足够的内存给它工作,如果没有虚拟内存正在交换(Paging)到磁盘,就是表明操作系统内存足够的最佳迹象

5.如果服务器只运行MySQL,所有不需要为操作系统以及查询处理保留的内存都可以用作MySQL缓存

6.大部分情况下最重要的缓存:

7.InnoDB缓冲池并不仅仅缓存索引:它还会缓存行的数据、自适应哈希索引、插入缓冲(Insert Buffer)、锁,以及其他内部数据结构,还使用缓冲池来帮助延迟写入,InnoDB严重依赖缓冲池

8.如果事先知道什么时候需要关闭InnoDB,可以在运行时修改innodb_max_dirty_pages_pct变量,将值改小,等待刷新纯种清理缓冲池,然后在脏页数量较少时关闭,可以监控the Innodb_buffer_pool_pages_dirty状态变量或者使用innotop来监控SHOW INNODB STATUS来观察脏页的刷新量

7.MyISAM的键缓存也被称为键缓冲,默认只有一个键缓存,但也可以创建多个,MyISAM自身只缓存索引,不缓存数据,最重要的配置项是key_buffer_size,不要超过索引的总大小,或者不超过操作系统缓存保留总内存的25%-50%,以更小的为准

8.了解MyISAM索引实际上占用多少磁盘空间,查询INFORMATION_SCHEMA表的INDEX_LENGTH字段,把它们的值相加,就可以得到索引存储占用空间

9.块大小也是很重要的(特别是写密集型负载),因为它影响了MyISAM、操作系统缓存,以及文件系统之间的交互,如果缓存块太小,可能会踫到写时读取

10.线程缓存保存那些当前没有与连接关联但是准备为后面新的连接服务的线程,当一个新的连接创建时,如果缓存中有线程存在,MySQL从缓存中删除一个线程,并且把它分配给这个新的连接,当连接关闭时,如果线程缓存还有空间的话,MySQL又会把线程放回缓存,如果没有空间的话,MySQL会销毁这个线程

11.thread_cache_size变量指定了MySQL可以保持在缓存中的线程数,一般不需要配置这个值,除非服务器会有很多连接请求

12.表缓存(Table Cache)和线程缓存的概念是相似的,但存储的对象代表的是表,缓存对象包含相关表.frm文件的解析结果,加上其他数据。表缓存可以重用资源,让服务器避免修改MyISAM文件头来标记表“正在使用中”,对InnoDB的重要性要小得多

12.表缓存的缺点是,当服务器有很多MyISAM表时,可能会导致关机时间较长,因为关机前索引块必须完成刷新,表都必须标记为不再打开

13.InnoDB数据字典(Data Dictionary),InnoDB自己的表缓存,当InnoDB打开一张表,就增加了一个对应的对象到数据字典

14.InnoDB没有将统计信息持久化,而是在每次打开表时重新计算,5.6以后可以打开innodb_use_sys_stats_table选项来持久化存储统计信息到磁盘

15.可以关闭InnoDB的innodb_stats_on_metadata选项来避免耗时的表统计信息刷新

16.如果可以,最好把innodb_open_files的值设置得足够大以使服务器可以保持所有的.ibd文件同时打开

E.配置MySQL的I/O行为

1.InnoDB I/O配置

2.MyISAM的I/O配置

F.配置MySQL并发

1.InnoDB并发配置

2.MyISAM并发配置

G.基于工作负载的配置

1.当服务器满载情况下运行时,请尝试记录所有的查询语句,因为这是最好的方式来查看哪种类型的查询语句占用资源最多,同时创建processlist快照,通过state或者command字段来聚合它们

2.优化BLOB和TEXT场景

3.优化排序(Filesorts):当MySQL必须排序BLOG或TEXT字段时,它只会使用前缀,然后忽略剩下部分的值

H.完成基本配置

1.tmp_table_size和max_heap_table_size,这两个设置控制使得Memory引擎的内存临时表能使用多大的内存

2.max_connections,这个设置的作用就像一个紧急刹车,以保证服务器不会因应用程序激增的连接而不堪重负,设置得以容纳正常可能达到的负载,并且要足够安全,能保证允许你登录和管理服务器

3.thread_cache_size,可以通过观察服务器一段时间的活动,来计算一个有理有据的值,250的上限是一个不错的估算值

4.table_cache_size,应该被设置得足够大,以避免总是需要重新打开和重新解析表的定义,可能通过观察Open_tables的值及其在一段时间的变化来检查该变量

I.安全和稳定的设置

1.expire_logs_days,如果启用了二进制日志,应该打开这个选项,可以让服务器在指定的天数之后清理旧的二进制日志

2.max_allowed_packet,防止服务器发送太大的包,也会控制多大的包可以被接收

3.max_connect_errors,如果知道服务器可以充分抵御蛮力攻击,可以把这个值设得非常大,以有效地禁用主机黑名单

4.skip_name_resolve,禁用了另一个网络相关和鉴权谁相关的陷阱:DNS查找

5.sql_mode,不建议修改

6.sysdate_is_now,可能导致与应用预期向后不兼容的选项

7.read_only,禁止没有特权的用户在备库做变更,只接受从主库传输过来的变更,不接受从应用来的变更,可以把备库设置为只读模式

8.skip_slave_start,阻止MySQL试图自动启动复制

9.slave_net_timeout,控制备库发现跟主库的连接已经失败并且需要重连之前等待的时间,设置为一分钟或更短

10.sync_master_info、sync_relay_log、sync_relay_log_info,5.5以后版本可用,解决了复制中备库长期存在的问题:不把它们的状态文件同步到磁盘,所以服务器崩溃后可能需要人来猜测复制的位置实际上在主库是哪个位置,并且可能在中继日志(Relay Log)里有损坏

J.高级InnoDB设置

1.innodb,如果设置为FORCE,只有在InnoDB可以启动时,服务器才会启动

2.innodb_autoinc_lock_mode,控制InnoDB如何生成自增主键值

3.innodb_buffer_pool_instances,在5.5以后,可以把缓冲池切分为多段,在高负载的多核机器上提升MySQL可扩展性的一个重要方式

4.innodb_io_capacity,有时需要把这个设置得相当高,才能稳定地刷新脏页

5.innodb_read_io_threads和innodb_write_io_threads,控制有多少后台线程可以被I/O操作使用

6.innodb_strict_mode,让MySQL在某些条件下把警告改成抛错,尤其是无效的或者可能有风险的CREATE TABLE选项

7.innodb_old_blocks_time,指定一个页面从LRU链表的“年轻”部分转移到“年老”部分之前必须经过的毫秒数,默认为0,设置为1000毫秒(1秒)非常有效

九、操作系统和硬件优化

A.什么限制了MySQL的性能

1.当数据可以放在内存中或者可以从磁盘中以足够快的速度读取时,CPU可能出现瓶颈,把大量的数据集完全放到大容量的内存中,以现在的硬件条件完全是可行的

2.I/O瓶颈,一般发生在工作所需的数据远远超过有效内存容量的时候,如果应用程序是分布在网络上的,或者如果有大量的查询和低延迟的要求,瓶颈可能转移到网络上

B.如何为MySQL选择CPU

1.可以通过检查CPU利用率来判断是否是CPU密集型的工作负载,还需要看看CPU使用率和大多数重要的查询的I/O之间的平衡,并注意CPU负载是否分配均匀

2.当遇到CPU密集型的工作时,MySQL通常可以从更快的CPU中获益,但还依赖于负载情况和CPU数量

3.MySQL复制也能在高速CPU下工作得非常好,而多CPU对复制的帮助却不大

4.多CPU在联机事务处理(OLTP)系统的场景中非常有用,在这样的环境中,并发可能成为瓶颈

C.平衡内存和磁盘资源

1.配置大量内存最终目的是避免磁盘I/O,最关键的是平衡磁盘的大小、速度、成本和其他因素,以便为工作负载提供高性能的表现

2.设计良好的数据库缓存(如InnoDB缓冲池),其效率通常超过操作系统的缓存,因为操作系统缓存是为通用任务设计的

3.数据库服务器同时使用顺序和随机I/O,随机I/O从缓存从受益最多

4.每个应用程序都有一个数据的“工作集”——就是这个工作确实需要用到的数据

5.工作集包括数据和索引,所以应该采用缓存单位来计数,一个缓存单位是存储引擎工作的数据最小单位

6.找到一个良好的内存/磁盘比例最好的方式是通过试验和基准测试

7.硬盘选择考虑因素:存储容量、传输速度、访问时间、主轴转速、物理尺寸

8.MySQL如何扩展到多个磁盘上取决于存储引擎和工作负载,InnoDB能很好地扩展到多个硬盘驱动器,然而,MyISAM的表锁限制其写的可扩展性,因此写繁重的工作加在MyISAM上,可能无法从多个驱动器中收益

D.固态存储

1.高质量闪存设备具备:

2.闪存的最重要特征是可以迅速完成多次小单位读取,但是写入更有挑战性。闪存不能在没有做擦除操作前改写一个单元(Cell),并且一次必须擦除一个大块。擦除周期是缓慢的,并且最终会磨损整个块

3.垃圾收集对理解闪存很重要。为了保持一些块是干净的并且可以被写入,设备需要回收脏块。这需要设备上有一些空闲空间

4.许多设备被填满后会开始变慢,速度下降是由于没有空闲块时必须等待擦写完成所造成的

5.固态存储最适合使用在任何有着大量随机I/O工作负载的场景下,随机I/O通常是由于数据大于服务器的内存导致的,闪存设备可能大大缓解这种问题

6.单线程工作负载也是另一个闪存的潜在应用场景

7.闪存也可以为服务器整合提供巨大的帮助

8.Flashcache,磁盘和内存技术的结合,适合以读为主的I/O密集型负载,并且工作集太大,用内存优化并不经济的情况

9.优化固态存储上的MySQL

E.为备库选择硬件

1.通常需要跟主库差不多的配置

F.RAID性能优化

1.RAID可以帮助做冗余、扩展存储容量、缓存,以及加速

2.RAID 0:如果只是简单的评估成本和性能,是成本最低和性能最高的RAID配置

3.RAID 1:在很多情况下提供很好的读性能,并且在不同的磁盘间冗余数据,所以有很好的冗余性,非常适合用来存放日志或者类似的工作

4.RAID 5:通过分布奇偶校验把数据分散到多个磁盘,如果任何一个盘的数据失效,都可以从奇偶校验块中重建,但如果有两个磁盘失效了,则整个卷的数据无法恢复,最经济的冗余配置。随机写是昂贵的,存放数据或者日志是一种可接受的选择,或者是以读为主的业务

5.RAID 10:对数据存储是个非常好的选择,由分片的镜像组成,对读和写都有良好的扩展性

6.RAID 50:由条带化的RAID 5组成

G.SAN和NAS

1.SAN(Storage Area Network)和NAS(Network-Attached Storage)是两个外部文件存储设备加载到服务器的方法,访问SAN设备时通过块接口,NAS设备通过基于文件的协议来访问

2.SAN允许服务器访问非常大量的硬盘驱动器,并且通常配置大容量智能高速缓存来缓冲写入

3.哪些工作放在SAN上不合适:执行大量的随机I/O的单线程任务

4.SAN的应用:

H.使用多磁盘卷

1.二进制日志和数据文件分离的真正的优势,是减少事故中同时丢失数据和日志文件的可能性

2.如果有很多磁盘,投入一些给事务日志可能会从中受益

I.网络配置

1.在生产服务器上启用skip_name_resolve是个好主意,损坏或缓慢的DNS解析对许多应用程序都是个问题,对MySQL尤严重,如果启用skip_name_resolve选项,MySQL将不会做任何DNS查找的工作

2.可以通过MySQL的back_log选项控制MySQL的传入TCP连接队列的大小,在每秒有很多连接创建和销毁的环境中,默认值50是不够的

3.网络物理隔离也是很重要的因素,尽可能避免实时的跨数据中心的操作是明智的

J.选择操作系统

1.一般企业级的MySQL部署在Windows上,但一般的企业级MySQL更多的还是部署在类UNIX操作系统上

K.选择文件系统

1.如果可能,最好使用日志文件系统,如ext3、ext4、XFS、ZFS或者JFS

2.可以调整文件系统的预读行为,因为这可能也是多余的

L.选择磁盘队列调度策略

1.在GUN/Linux上,队列调度决定了到块设备的请求实际上发送到底层设备的顺序,默认情况下使用cfq(Completely Fair Queueing,完全公平排队)策略,在MySQL的工作负载类型下,cfq会导致很差的响应时间,因为会在队列中延迟一些不必要的请求

2.cfq之外的两个选项都适合服务器级的硬件,noop调度适合没有自己的调度算法的设备,deadline则对RAID控制器和直接使用的磁盘都工作良好

M.线程

1.MySQL每个连接使用一个线程,另外还有内部处理线程、特殊用途的线程,以及所有存储引擎创建的线程

2.MySQL确实需要内核级线程的支持,而不只是用户级线程,这样才能更有效地使用多个CPU,另外也需要有效的同步原子

N.内存交换区

1.内存交换对MySQL性能影响是很糟糕的,它破坏了缓存在内存的目的,并且相对于使用很小的内存做缓存,使用交换区的性能更差

2.在GNU/Linux上,可以用vmstat来监控内存交换,最好查看si和so列报告的内存交换I/O活动,这比看swpd列报告的交换区利用率更重要,最佳为0

3.设置/proc/sys/vm/swappiness为一个很小的值

4.修改存储引擎怎么读取和写入数据,使用innodb_flush_method=0_DIRECT减轻I/O压力

5.使用MySQL的memlock配置项,可以把MySQL锁定在内存

O.操作系统状态

1.vmstat

2.iostat

3.CPU密集型的机器,vmstat输出通常在us列会有一个很高的值,也可能在sy列有很高的值

4.I/O密集型工作负载下,vmstat会显示很多处理器在非中断休眠(b列)状态,并且wa这一列的值很高

5.发生内存交换的机器可能在swpd列有一个很高的值

十、复制

A.复制概述

1.MySQL支持两种复制方式:基于行的复制和基于语句的复制,都是通过在主库上记录二进制日志、在备库重放日志的方式来实现异步的数据复制

2.复制通常不会增加主库的开销,主要是启用二进制日志带来的开销,但出于备份或及时从崩溃中恢复的目的,这点开销也是必要的

3.通过复制可以将读操作指向备库来获得更好的读扩展,但对于写操作,除非设计得当,否则并不适合通过写复制来扩展写操作

4.复制解决的问题:

5.复制如何工作

B.配置复制

1.在每台服务器上创建复制帐号

2.配置主库和备库

3.通知备库连接到主库并从主库复制数据

4.推荐的复制配置

C.复制的原理

1.基于语句的复制

2.基于行的复制

3.基于行或基于语句:哪种更优

4.复制文件

5.发送复制事件到其他备库:log_slave_updates,可以让备库变成其他服务器的主库

6.复制过滤选项

D.复制拓扑

1.基本原则:

2.一主库多备库

3.主动-主动模式下的主主复制:auto_increment_increment和auto_increment_offset可以让MySQL自动为INSERT语句选择不互相冲突的值

4.主动-被动模式下的主主复制:其中一台服务器是只读的被动服务器

5.拥有备库的主主结构:增加了冗余,能够消除站点单点失效的问题

6.环形复制:每个服务器都是在它之前的服务器的备库,是在它之后的服务器的主库

7.分发主库事实上也是一个备库,提取和提供主库的二进制日志

8.树或金字塔形:减轻了主库的负担,但中间层出现的任何错误都会影响到多个服务器

9.定制的复制方案

E.复制和容量规划

1.写操作通常是复制的瓶颈,并且很难使用复制来扩展写操作

2.在构建一个大型应用时,有意让服务器不被充分使用,这应该是一种聪明并且蔓延的方式,尤其在使用复制的时候,有多余容量的服务器可以更好地处理负载尖峰,也有更多能力处理慢速查询和维护工作,并且能够更好地跟上复制

F.复制管理和维护

1.在主库上,可以使用SHOW MASTER STATUS命令来查看当前主库的二进制日志位置和配置

2.从库上,使用SHOW SLAVE STATUS

十一、可扩展的MySQL

A.什么是可扩展性

1.可扩展性表明了当需要增加资源以执行更多工作时系统能够获得划算的等同提升(equal bang for the buck)的能力,缺乏扩展能力的系统在达到收益递减的转折点后,将无法进一步增长

2.可扩展性就是能够通过增加资源来提升容量的能力

B.扩展MySQL

1.规划可扩展性最困难的部分是估算需要承担的负载到底有多少,还需要大致正确地估计日程表,需要知道底线在哪里

2.可以做的准备工作:优化性能、购买性能更强的硬件

3.向上扩展(垂直扩展)意味着购买更多性能强悍的硬件

4.向外扩展(横向扩展、水平扩展):复制、拆分、数据分片

5.通过多实例扩展

6.通过集群扩展

7.向内扩展,对不再需要的数据进行归档和清理

8.保持活跃数据独立

C.负载均衡

1.在一个服务器集群中尽可能地平均负载量,通常在服务器前端设置一个负载均衡器

十二、高可用性

A.什么是高可用性

1.高可用性不是绝对的,只有相对更高的可用性,100%的可用性是不可能达到的

2.可用性每提高一点,所花费的成本都会远超之前,可用性的效果和开销的比例并不是线性的

B.导致宕机的原因

1.运行环境问题,最普遍的问题是磁盘空间耗尽

2.性能问题,最普遍的原因是运行很糟糕的SQL,或服务器BUG或错误的行为

3.糟糕的Schema和索引设计

4.复制问题通常由于主备数据不一致导致

5.数据丢失通常由于DROP TABLE的误操作导致,并总是伴随着缺少可用备份的问题

C.如何实现高可用性

1.可以通过同时进行以下两步来获得高可用性

2.提升平均失效时间(MTBF)

3.降低平均恢复时间(MTTR)

D.避免单点失效

1.系统中任何不冗余的部分都是一个可能失效的单点

2.可以采用两种方法来为系统增加冗余:增加空余容量和重复组件

3.共享存储或磁盘复制

4.MySQL同步复制

5.基于复制的冗余

E.故障转移和故障恢复

1.冗余一点也不会增加可用性或减少宕机,和故障转移结合可以帮助更快地恢复,故障转移最重要的部分就是故障恢复

2.提升备库或切换角色

3.虚拟IP地址或IP接管

4.中间件解决方案,可以使用代理、端口转发、网络地址转换或者硬件负载均衡来实现故障转移和故障恢复

5.在应用中处理故障转移

十三、云端的MySQL

A.云的优点、缺点和相关误解

1.优点:

2.缺点:

B.MySQL在云端的经济价值

1.云托管比较适合尚处于初级阶段的企业,或者那些持续接触新概念并且本质上是以适用为主的企业

2.大量使用的策略是尽可能又快又便宜地开发和发布应用

3.运行不是很重要的基础设施

C.云中的MySQL的可扩展性和高可用性

1.数据库通常是一个应用系统中主要或唯一的有状态并且持久化的组件

2.MySQL并不具备在一个无共享集群中的对等角色服务器之间迁移的能力

D.四种基础资源

1.CPU通常少且慢

2.内在大小受限制

3.I/O的吞吐量、延迟以及一致性受到限制

4.网络性能还比较好

E.MySQL在云主机上的性能

1.需要高并发的工作负载并不是非常适合云计算

2.那些需要大量I/O的工作负载在云中并不总是表现很好

F.MySQL数据库即服务(DBaaS)

1.将数据库本身作为云资源

十四、应用层优化

A.常见问题

1.什么东西在消耗系统中每台主机的CPU、磁盘、网络,以及内存资源?这些值是否合理?如果不合理,对应用程序做基本的检查,看什么占用了资源

2.应用真是需要所有获取到的数据吗?

3.应用在处理本应由数据库处理的事情吗,或者反过来?

4.应用执行了太多的查询?

5.应用执行的查询太少了?

6.应用创建了没必要的MySQL连接吗?

7.应用对一个MySQL实例创建连接的次数太多了吗?

8.应用做了太多的“垃圾”查询?

9.应用使用了连接池吗?这既可能是好事,也可能是坏事

10.应用是否使用长连接?

11.应用是否在不使用的时候还保持连接撕开?

B.Web服务器问题

1.最常见的问题是保持它的进程的存活(alive)时间过长,或者在各种不同的用途下混合使用,而不是分别对不同类型的工作进行优化

2.如果用一个通用目的的Apache配置直接用于Web服务,最后很可能产生很多重量级的Apache进程

3.不要使用Apache来做静态内容服务,或者至少和动态服务使用不同的Apache实例

4.进程存活时间变短策略:

C.缓存

1.被动缓存除了存储和返回数据外不做任何事情;主动缓存在访问未命中时做一些额外工作

2.应用可以缓存部分计算结果,所以应用层缓存可能比更低层次的缓存更有效,可以节省两方面的工作:获取数据以及基于这些数据进行计算,重点是缓存命中率可能更低,并且可能使用较多的内存

3.应用层缓存:

4.缓存控制策略

5.可以在后台预先请求一些页面,并将结果存为静态页面,好处:

D.MySQL的替代品

1.搜索:Lucene和Sphinx

2.简单的键值存储:Redis

3.结构化数据:Hadoop

十五、备份与恢复

A.为什么要备份

1.灾难恢复

2.人们改变想法

3.审计

4.测试

B.定义恢复需求

1.规划备份和恢复策略时,有两个重要的需求:恢复点目标(PRO)和恢复时间目标(RTO)

C.设计MySQL备份方案

1.建议

2.如果可能,关闭MySQL做备份是最简单最安全的,需要考虑:锁时间、备份时间、备份负载、恢复时间

3.逻辑备份优点:

4.逻辑备份的缺点:

5.物理备份优点:

6.物理备份缺点:

7.除非经过测试,不要假定备份是正常的

8.建议混合使用物理和逻辑两种方式来做备份

9.MySQL备份需要考虑的几点:

10.差异备份是对自上次全备份后所有改变的部分做备份,而增量备份则是自从任意类型的上次备份后所有修改做的备份

11.差异、增量备份的建议:

12.数据一致性:当备份时,应该考虑是否需要数据在指定时间点一致

13.文件一致性:每个文件的内部一致性

14.从备库中备份最大的好处是可以不干扰主库,故意将一个备库延时一段时间对于某些灾难场景非常有用

D.管理和备份二进制日志

1.expire_log_days变量MySQL定期清理日志

E.备份数据

1.生成逻辑备份

2.文件系统快照

F.从备份中恢复

1.恢复步骤:

G.备份和恢复工具

1.MySQL Enterprise Backup

2.Percona XtraBackup

3.mylvmbackup

4.Zmanda Recovery Manager

5.mydunper

6.mysqldump

十六、MySQL用户工具

A.接口工具

1.MySQL Workbench

2.SQLyog

3.phpMyAdmin

4.Adminer

B.命令行工具集

1.Percona Toolkit

2.Maatkit and Aspersa

3.The openark kit

4.MySql workbench

C.SQL实用集

1.common_schema

2.mysql-sr-lib

3.MySQL UDF仓库

4.MySQL Forge

D.监测工具

1.开源的监控工具

2.商业监控系统

3.Innotop的命令行监控

上一篇 下一篇

猜你喜欢

热点阅读