前言

Github:https://github.com/HealerJean

博客:http://blog.healerjean.com

1、问题出现和解决

1.1、问题1:应用连接被打满

### Error updating database. Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is com.alibaba.druid.pool.GetConnectionTimeoutException: wait millis 5000, active 10, maxActive 10, creating 0

1.1.1、问题出现

在一次JD预发环境验证保险保单的时候,只有一台服务,数据库连接配置为:maxWait: 5000maxActive: 10initialSize: 5。很高流量的运费险到达之后,就出现了上面的报错信息。报错信息说明,已经把数据库连接池打满了,并且等待了 5s 还是不能获取连接,所以报错了。

1.1.2、问题解决

查询总连接数,增大连接,后来设置成100了解决了

2、监控指标分析

2.1、磁盘性能指标

IOPS 和 数据吞吐量适用于不同的场合:

追求IOPS:读取 10000个 1KB 文件,用时10秒 Throught (吞吐量)=1MB/s ,IOPS=1000

追求吞吐量:读取1个10MB文件,用时0.2秒 Throught(吞吐量)=50MB/s, IOPS=5

2.1.1、IO Thruput(KB)IO读写吞吐量

read: 磁盘读吞吐量

write: 磁盘写吞吐量

image-20211231114430211

2.1.2、IOPS:磁盘的读/写操作次数

read: 每秒磁盘的读操作次数

write: 每秒磁盘的写操作次数

image-20211231114534339

2.2、机器性能指标

2.2.1、cpu usage cpu load

cpu usagecpu 利用率,就是程序对CPU时间片的占用情况

load average 表示的是 CPU的负载,包含的信息不是CPU的使用率状况,而是在一段时间内CPU正在处理以及等待CPU 处理的进程数之和的统计信息,也就是是一段时间内正在使用和等待使用CPU的平均任务数。这个数字越小越好,CPU利用率高,并不意味着负载就一定大

如果load average值长期大于系统CPU的个数则说明CPU很繁忙,负载很高,可能会影响系统性能,导致系统卡顿响应时间长等等

举例来说:如果我有一个程序它需要一直使用 cpu 的运算功能,那么此时 cpu 的使用率可能达到100%,但是 cpu 的工作负载则是趋近于 “1”,因为 cpu 仅负责一个工作嘛!如果同时执行这样的程序两个呢?cpu 的使用率还是 100% ,但是工作负载则变成2了。所以也就是说,当cpu的工作负载越大,代表cpu必须要在不同的工作之间进行频繁的工作切换。

2.2.1.1、正常值

CPU利用率参考值:15.30 ,最小值 10.5,最大 21.75

一般能够被接受的值是 load average <= CPU核数 * 0.7

image-20211231114348705

2.1.2、Network Flow(kb):网卡出/入口流量

recv:网卡入口流量

send:网卡出口流量

image-20211231114453562

2.1.2.1、正常值

2.1.3、IOUTIL:机器的 IO 使用率

image-20211231114935940

2.3、MYSQL SQL相关

2.3.1、SQL:语句操作数量

ins: insert 语句操作的数量

upd: update 语句操作的数量

del: delete语句操作的数量

image-20211231113958428

2.3.2、ROWS:语句影响行

insinsert 语句操作的数量

updupdate语句操作的数量

deldelete语句操作的数量

read:读取的行数

image-20211231114125454

2.1.3、QPS/TPS

image-20211231115005063

2.4、Innodb

2.4.1、Innodb Buffer Poll Hit Ratio

image-20211231115023948

2.4.2、Thread Connect:当前已连接线程数

image-20211231115143202

2.4.3、Thread Running:当前活跃连接数

image-20211231115231959

2.4.4、Thead Other Status:线程其他状态

thead_create:新创建线程数

thread_cachethread_cache 中已缓存的线程数

image-20211231115329218

2.4.5、Innodb Buffer Poll Status(MB)

pages_data: Innodb缓存池数据页占用量

pages_free: Innodb缓存池空闲页占用量

pages_dirty: Innodb缓存池脏页占用量

image-20211231115503255

2.4.6、Inodb Pages Flush

pages_flush: Innodb 缓存池每秒flush 操作请求数

image-20220112214016757

2.4.7、Innodb IOPS

data_reads: Innodb 数据每秒物理读请求数

data_writes: Innodb 数据每秒物理写请求数

image-20220112214208750

2.4.8、Innodb IO Thruput

data_read: Innodb 数据每秒物理读取量

data_written: Innodb 数据每秒物理写入量

image-20220112214405752

2.4.9、Innodb Main Thread

read_view: 当前打开 read view 个数

query_queue: 当前 Innodb 等待队列中的线程数

query_inside: 当前 Innodb 内核线程数

image-20220112214634293

2.4.10、Undo History List Length

his_list: 当前 undo 表空间中还未purge 的事务个数

image-20220112214743539

2.4.11、Innodb ReDo Log(byte)

log_unflush: Innodb当前还未flush的redo日志大小

log_unchkpt: Innodb当前还未checkpoint的redo日志大小

image-20220112215001849

3、数据源信息

3.1、连接相关

3.1.1、max_connections

**max_connections ** MYSQL 服务端允许的最大连接会话数量; (maxAcvie以它为主)

默认值是15MySQL 允许的最大连接数上限是 16384

mysql> show variables like 'max_connections';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 3100 |
+-----------------+-------+

3.1.2、Thread

Threads_connected: 这个数值指的是打开的连接数,跟 show processlist 结果相同,表示当前连接数。

Threads_running:是代表当前并发数,这个数值指的是激活的连接数,这个数值一般远低于 connected 数值。

mysql> show status like 'Threads%';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Threads_cached | 429 |
| Threads_connected | 102 | 
| Threads_created | 1915 |
| Threads_running | 3 |
+-------------------+-------+

3.1.3、Max_used_connections

max_user_connections这MySQL服务器过去的最大连接数是245,没有达到最大连接数的上限

理想:max_used_connections / max_connections * 100%85%

mysql>show global status like 'Max_used_connections';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Max_used_connections | 762 |
+-------------------+-------+

3.1.3.1、查看上次 MYSQL 启动后的最大连接数

mysql> show global status like 'Max_used_connections';
+-----------------------------------+---------------------+
| Variable_name                     | Value               |
+-----------------------------------+---------------------+
| Max_used_connections              | 762                   |
| Max_used_connections_time         | 2021-04-29 17:36:51 |

3.1.4、innodb_thread_concurrency

支持的最大并发执行的线程数:这个是 innodb内核的并发线程处理参数,即同一时刻能够进入 innodb 层次并发执行的线程数(「注意是并发不是并行」)。比如前端有 100 个连接,发来 1000sql,如果这个参数被设置成2。那么这 1000sql 中,最多只有 2sqlinnodb 内核运行。其它都得等。(事实上,处理过程很复杂,可以先这么理解,不是所有 sql 都需要放在 Innodb 内核处理的)。

3.1.4、取值

3.1.4.1、默认 0

默认 0 ,则表示没有并发线程数限制,所有请求都会直接请求线程执行。注意:当 innodb_thread_concurrency设置为 0 时,则 innodb_thread_sleep_delay 的设置将会被忽略,不起作用。如果数据库没出现性能问题时,使用默认值即可。

3.1.4.2、大于 0

当 > 0,则表示有并发数限制

1、 当一个新的请求发起时,会检查当前并发线程数是否达到了innodb_thread_concurrency 的限制值,如果有,则需要 sleep 一段时间,然后再再次请求

2、如果再次请求时,当前并发数还是达到限制值,那么就会进入 FIFO 队列等待执行。

3、当进入到内核执行时,会得到一个消费凭证 ` ticket,则这个线程,在后面的多次进入 innodb 执行操作是都不需要重复上面的检查步骤,当把次数消费完,那么这个线程就会被驱逐,等待下次再次进入 Innodb,再重新分配 ticket`。

4、那些等待获取锁的线程则不会被计入到并发执行线程 innodb_thread_concurrency 的数量中。

3.1.5、建议配置

⬤ 当并发用户线程数量小于 64,建议设置 innodb_thread_concurrency = 0

⬤ 如果负载不稳定,时而低,时而高到峰值,建议先设置 innodb_thread_concurrency = 128,并通过不断的降低这个参数,96 , 80 , 64 等等,直到发现能够提供最佳性能的线程数,例如,假设系统通常有 4050 个用户,但定期的数量增加至 6070,甚至 200。你会发现,性能在 80个并发用户设置时表现稳定,如果高于这个数,性能反而下降。在这种情况下,建议设置 innodb_thread_concurrency参数为80,以避免影响性能;

注意:

⬤ 如果 DB 服务器上还允许其他应用,需要限制 mysql 的线程使用情况,则可以设置可分配给 DB的线程数,但是不建议 DB上跑其他应用,也不建议这么设置,因为这样可能导致数据库没有对硬件最优使用;

⬤ 设置过高值,可能会因为系统资源内部争夺导致性能下降「在大多数情况下,最佳的值是小于并接近虚拟CPU的个数;」

⬤ 定期监控和分析 DB,因为随着数据库负载的变化,业务的增加,innodb_thread_concurrency 也需要动态的调整

ContactAuthor