MySQL:MySQL性能优化经验总结

2022-01-14  本文已影响0人  dex0423

1. 引擎选择

在创建表的时候,可依据应用场景选择合适的引擎。

2. 读写分离 & 一主多备

在实际的应用中,绝大部分情况都是读远大于写。Mysql提供了读写分离的机制,所有的写操作都必须对应到Master,读操作可以在 Master和Slave机器上进行,Slave与Master的结构完全一样,一个Master可以有多个Slave,甚至Slave下还可以挂 Slave,通过此方式可以有效的提高DB集群的 QPS。
所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。

注意:所有的写操作都是先在Master上操作,所以Master是集群的瓶颈,当写操作过多,会严重影响到Master的稳定性,如果Master挂掉,整个集群都将不能正常工作。

3. 分库分表

3.1. 分库分表的基本原理

垂直拆分:是指按功能模块拆分,垂直拆分解决表与表之间的 I/O 竞争。比如分为订单库、商品库、用户库...这种方式多个数据库之间的表结构不同。
水平拆分:将同一个表的数据进行分块保存到不同的数据库中,水平拆分解决单表中数据量增长出现的压力。这些数据库中的表结构完全相同。

3.2. 垂直分表

垂直分表,是基于列(字段)对表格进行横向拆分。

垂直分表,一般是针对那种几百列的大表,也避免查询时,数据量太大造成的“跨页”问题。

分表能够解决单表数据量过大带来的查询效率下降的问题,但是,却无法给数据库的并发处理能力带来质的提升。面对高并发的读写访问,当数据库master服务器无法承载写操作压力时,不管如何扩展slave服务器,此时都没有意义了。因此,我们必须换一种思路,对数据库进行拆分,从而提高数据库写入能力,这就是所谓的分库。

3.3. 垂直分库

垂直分库,是针对一个系统中的不同业务进行拆分,比如用户User一个库,商品Producet一个库,订单Order一个库。

垂直切分后,一般放在多个服务器上,而不是一个服务器上。这是因为,一个购物网站对外提供服务,会有用户,商品,订单等的CRUD。没拆分之前, 全部都是落到单一的库上的,这会让数据库的单库处理能力成为瓶颈。

按垂直分库后,如果还是放在一个数据库服务器上, 随着用户量增大,这会让单个数据库的处理能力成为瓶颈,还有单个服务器的磁盘空间,内存,tps等非常吃紧。 所以我们要拆分到多个服务器上,这样上面的问题都解决了,以后也不会面对单机资源问题。
数据库往往最容易成为应用系统的瓶颈,而数据库本身属于“有状态”的,相对于Web和应用服务器来讲,是比较难实现“横向扩展”的。 数据库的连接资源比较宝贵且单机处理能力也有限,在高并发场景下,垂直分库一定程度上能够突破IO、连接数及单机硬件资源的瓶颈。数据库业务层面的拆分,能对不同业务的数据分别的进行管理,维护,监控,扩展等。

3.4. 水平分表(不单独使用)

针对数据量巨大的单张表(比如订单表),按照某种规则(RANGE,HASH取模等),切分到多张表里面去。

生产环境中,水平分表一般不单独使用,而是和水平分库一起使用,做水平分库分表。

3.5. 水平分库(一般与水平分表同时使用)

将单张表的数据切分到多个服务器上去,每个服务器具有相应的库与表,只是表中数据集合不同。水平分库分表能够有效的缓解单机和单库的性能瓶颈和压力,突破IO、连接数、硬件资源等的瓶颈。

3.6. 分库分表的标准

3.6. 分库分表存在的问题

维度的问题解决办法:记录【两份数据】,一份按照用户纬度分表,一份按照商品维度分表。

3.7. 分库分表产品方案

3. 分区分片

3.1. 分区原理

表分区,就是将数据量比较大的表,在物理上分成若干个小表,从逻辑来看还是一个大表。MySQL 5 之后才有了数据表分区功能。
数据库的应用分为两类:一类是OLTP(在线事务处理),如Blog、电子商务、网络游戏等;另一类是OLAP(在线分析处理),如数据仓库、数据集市。

MySQL的分区字段,必须包含在主键字段内。

3.2. 分区策略

3.2. 分区使用场景:

3.3. 分表和分区的区别

3.4. 分片策略

分片,是把数据库横向扩展(Scale Out)到多个物理节点上的一种有效的方式。其主要目的,是为突破单节点数据库服务器的 I/O 能力限制,解决数据库扩展性问题。Shard这个词的意思是“碎片”。如果将一个数据库当作一块大玻璃,将这块玻璃打碎,那么每一小块都称为数据库的碎片(DatabaseShard)。将整个数据库打碎的过程就叫做分片,可以翻译为分片。
形式上,分片可以简单定义为将大数据库分布到多个物理节点上的一个分区方案。每一个分区包含数据库的某一部分,称为一个片,分区方式可以是任意的,并不局限于传统的水平分区和垂直分区。一个分片可以包含多个表的内容甚至可以包含多个数据库实例中的内容。每个分片被放置在一个数据库服务器上。一个数据库服务器可以处理一个或多个分片的数据。系统中需要有服务器进行查询路由转发,负责将查询转发到包含该查询所访问数据的分片或分片集合节点上去执行。

3.5. 分片和分区的区别

分片和分区,有很多的相似之处。有的时候,分片(Sharding) 也被近似等同于水平分区(Horizontal Partitioning),网上很多地方也用水平分区来指代 分片(Sharding)。


image.png

4. 优化连接池

SHOW VARIABLES LIKE 'max_connections';

-- 查询数据库目前实际连接的并发数是多少

SHOW STATUS LIKE 'max_used_connections';

-- 在MySQL配置文件 /etc/my.cnf 中设置 max_connections=3000,表示修改最大连接数为3000。

注意:需要重启 MySQL 才能生效。

-- MySQL为每个连接创建缓冲区,所以不应该盲目上调最大连接数。

如果最大连接数达到了上面设置的 3000,会消耗大约 800M 内存。

开启连接池: Pooling=true,默认开启
复用时重置连接状态: ConnectionReset=True
保持连接设置: CacheServerProperties=True
连接超时回收(秒): ConnectionLifeTime=300
支持的最大连接数量: Max Pool Size=100
保持最小的连接数量: Min Pool Size=10

5. 优化请求堆栈

6. 修改连接超时时间

7. 优化内存缓冲池

8. 优化并发线程数

cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c

-- 查看cpu核心数

cat /proc/cpuinfo | grep "cores"|uniq

9. 优化线程池

  • 客户端发起连接到 MySQL Server 后,MySQL Server监听进程监听到新的请求,然后 Sever 会为其分配一个新的 thread去处理此请求。
  • 从建立连接之开始,CPU要给它划分一定的 thread stack,然后进行用户身份认证,建立上下文信息,最后请求完成,关闭连接,同时释放资源。
  • 在高并发的情况下,这个过程将给系统带来巨大的压力,不能保证性能。MySQL服务器的线程数需要在一个合理的范围之内,这样才能保证MySQL服务器健康平稳地运行。
9.1 查看线程池的状态:
mysql> show variables like 'thread%';
+--------------------+---------------------------+
| Variable_name      | Value                     |
+--------------------+---------------------------+
| thread_cache_size  | 64                        |
| thread_concurrency | 10                        |
| thread_handling    | one-thread-per-connection |
| thread_stack       | 262144                    |
+--------------------+---------------------------+
thread_cache_size
1G —> 8
2G —> 16
3G —> 32
>3G —> 64

-- 在 mysql 命令行中设置:

mysql> set global thread_cache_size=64;
thread_concurrency
mysql> set global thread_concurrency=4;
thread_handling
thread_stack
9.2 查看线程使用情况:
mysql>  show global status like 'Thread%';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Threads_cached    | 41    |
| Threads_connected | 53    |
| Threads_created   | 541   |
| Threads_running   | 4     |
+-------------------+-------+
Threads_cached

MySQL里面为了提高客户端请求创建连接过程的性能,提供了一个连接池也就是 Thread_cache 池(大小是thread_cache_size),将空闲的连接线程放在连接池中,而不是立即销毁。
这样的好处就是,当又有一个新的请求的时候,mysql不会立即去创建连接 线程,而是先去 Thread_Cache 中去查找空闲的连接线程,如果存在则直接使用,不存在才创建新的连接线程。Thread_cache 值表示已经被线程缓存池缓存的线程个数。

Threads_connected

当前处于连接状态的线程个数,等于 show processlist。

Threads_created

Threads_created 表示创建过的线程数,如果发现 Threads_created 值过大的话,表明MySQL服务器一直在创建线程,这也是比较耗资源,可以适当增加配置文件中 thread_cache_size 值。

Threads_running

处于激活状态的线程的个数,这个一般都是远小于Threads_connected的。

10. 优化日志

错误日志:启动、关闭、运行时 产生的异常记录,建议开启,设置 log_error

查询日志:客户端连接和执行的脚本,建议关闭,设置 general_log

慢查询日志:记录超时的查询,记录不适用索引的查询等,建议关闭,设置 slow_query_log

二进制日志:用于数据同步复制,需发送的数据日志,多用于集群,如需开启,设置 log_bin

中继日志:用于数据同步复制时,接收到的数据日志,多用于集群,如需开启,设置 relay_log

11. 锁优化

11.1. innodb 锁优化

Innodb 存储引擎由于实现了行级锁定,虽然在锁定机制的实现方面所带来的性能损耗可能比表级锁定会要更高一些,但是在整体并发处理能力方面要远远优于MyISAM 的表级锁定的。

减少 innodb 死锁产生概率的建议:

11.2. MyISAM 锁优化

MyISAM 表锁优化建议优化MyISAM 存储引擎锁定问题的时候,最关键的就是如何让其提高并发度。由于锁定级别是不可能改变的了,所以我们首先需要尽可能让锁定的时间变短,然后就是让可能并发进行的操作尽可能的并发。

参考文章:
上一篇 下一篇

猜你喜欢

热点阅读