前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL 8.0 新特性:Resource Group 与写入性能优化实战

MySQL 8.0 新特性:Resource Group 与写入性能优化实战

原创
作者头像
王文安@DBA
修改2020-11-19 10:29:56
1.4K0
修改2020-11-19 10:29:56
举报

前言

离 8.0 正式发布已经有一段时间了,随着小版本的不断迭代,MySQL 8.0 也加入了很多有意思/有价值的特性,例如原子 DDL,WriteSet复制,二级密码等,在专栏中也有非常多的介绍。本文介绍的特性是 Resource Group,即资源组,主要用来调度 MySQL 的资源用,其实是一个兼顾了实用性和技巧性的功能,且刚好能解决 MySQL 8.0 对写入性能的一个“负优化”。

资源组

简介

MySQL 本身是一个单进程多线程的架构,除了处理用户连接的线程外,还有很多的后台线程,例如 flush_thread,purge_thread,read_thread,write_thread 等。在旧版本中,这些线程都是同样的优先级,共享所有的 CPU 资源,也无法像 cgroup 一样把一些线程绑定到固定的核心上,独占一部分 CPU 资源。

而面对实际业务的时候,根据业务的特点来调度资源,应对不同的业务高峰期是常用的手段之一,比如业务高峰期来临之前,让业务相关的线程独占一部分 CPU 资源,提高业务处理能力。

在 MySQL 8.0 中就可以使用资源组来满足这一类需求。使用方式也比较简单:创建一个资源组,然后把线程绑定到对应的资源组即可。

如何使用

创建资源组的语法如下:

代码语言:txt
复制
CREATE RESOURCE GROUP group_name
    TYPE = {SYSTEM|USER}
    [VCPU [=] vcpu_spec [, vcpu_spec] ...]
    [THREAD_PRIORITY [=] N]
    [ENABLE|DISABLE]

vcpu_spec: {N | M - N}
  • TYPE:设置资源组的类型,MySQL 的后台线程只能绑定到 SYSTEM 的资源组,用户线程只能绑定到 USER。
  • VCPU:用逗号分隔的序号列表,或者是用类似于 1-10 的范围形式。
  • THREAD_PRIORITY:设置优先级,数字越小,优先级越高。

绑定资源组的语法如下:

代码语言:txt
复制
 SET RESOURCE GROUP group_name FOR thread_id1,thread_id2 ......

绑定是即时生效的,命令执行完之后立刻就能看到效果。

写入性能优化

简介

这个问题实际上是跑 8.0 基准测试的时候发现的:同配置的情况下,8.0 的写入性能相比 5.7 是下降的,而且下降的幅度并不能当做随机误差来看待。因此研究了一下 8.0 的变化,发现有一项优化:把 log_writer 和 log_flusher 拆分成了单独的线程。使用双 1 的事务提交策略时,每次提交事务都会需要写 log,是不是这两个线程单独拆出来之后,因为抢不到 CPU 资源影响到了写入性能?

测试一下

这次测试的环境:

  • 腾讯云的高 IO 型 CVM,本地 NVME 磁盘作为存储,16 核心,64GB 内存,debian 9.13。
  • MySQL 8.0.22,sysbench-1.0.20。
  • 事务提交策略为双 1,数据量为 5 张表,每张表 1000 万行数据,可以全部加载到 buffer_pool。

为了使用资源组,需要先在系统层配置一下环境:

代码语言:txt
复制
apt-get install libcap2-bin
setcap cap_sys_nice+ep /usr/sbin/mysqld
getcap /usr/sbin/mysqld
显示:/usr/sbin/mysqld = cap_sys_nice+ep 即可

重启 MySQL 之后,预热好数据,开启 write_only 的测试,然后再设置资源组:

代码语言:txt
复制
CREATE RESOURCE GROUP bg_thread1 TYPE = system VCPU = 0  THREAD_PRIORITY = -20;
CREATE RESOURCE GROUP bg_thread2 TYPE = system VCPU = 1  THREAD_PRIORITY = -20;
CREATE RESOURCE GROUP other_thread TYPE = system VCPU = 2-15  THREAD_PRIORITY = 0;

通过系统表找到 log_writer 和 log_flusher 的 thread_id,以及测试线程的 ID:

代码语言:txt
复制
mysql> select THREAD_ID,NAME from performance_schema.threads;
+-----------+---------------------------------------------+
| THREAD_ID | NAME                                        |
+-----------+---------------------------------------------+
|         1 | thread/sql/main                             |
|       783 | thread/sql/one_connection                   |
|         3 | thread/innodb/io_ibuf_thread                |
|         4 | thread/innodb/io_log_thread                 |
 |        45 | thread/innodb/log_checkpointer_thread       |
|        46 | thread/innodb/log_flush_notifier_thread     |
|        47 | thread/innodb/log_flusher_thread            |
|        48 | thread/innodb/log_write_notifier_thread     |
|        49 | thread/innodb/log_writer_thread             |
|        50 | thread/innodb/srv_lock_timeout_thread       |
|        51 | thread/innodb/srv_error_monitor_thread      |
|        52 | thread/innodb/srv_monitor_thread            |
......

thread/sql/one_connection 就是用户连接,log_flusher_thread 和 log_writer_thread 就是要找的系统内部线程。

由于测试的用户连接过多,可以写个简单的脚本生成用户线程的绑定语句:

代码语言:txt
复制
#!/bin/bash

ID_LIST=`mysql -Ne "select concat(THREAD_ID,',') from performance_schema.threads where name = 'thread/sql/one_connection';"`

echo "SET RESOURCE GROUP other_thread FOR" ${ID_LIST%,*}";"

绑定系统内部线程的语句如下:

代码语言:txt
复制
SET RESOURCE GROUP bg_thread1 FOR 47;
SET RESOURCE GROUP bg_thread2 FOR 49;

执行完毕之后,sysbench 输出的结果如下:

代码语言:txt
复制
[ 380s ] thds: 48 tps: 7329.74 qps: 29318.27 (r/w/o: 0.00/29318.27/0.00) lat (ms,95%): 10.46 err/s: 0.00 reconn/s: 0.00
[ 390s ] thds: 48 tps: 7385.89 qps: 29543.85 (r/w/o: 0.00/29543.85/0.00) lat (ms,95%): 10.46 err/s: 0.00 reconn/s: 0.00
[ 400s ] thds: 48 tps: 7245.54 qps: 28982.46 (r/w/o: 0.00/28982.46/0.00) lat (ms,95%): 10.65 err/s: 0.00 reconn/s: 0.00
[ 410s ] thds: 48 tps: 7326.35 qps: 29305.91 (r/w/o: 0.00/29305.91/0.00) lat (ms,95%): 10.65 err/s: 0.00 reconn/s: 0.00
[ 420s ] thds: 48 tps: 7315.21 qps: 29260.75 (r/w/o: 0.00/29260.75/0.00) lat (ms,95%): 10.46 err/s: 0.00 reconn/s: 0.00
[ 430s ] thds: 48 tps: 7305.01 qps: 29221.02 (r/w/o: 0.00/29221.02/0.00) lat (ms,95%): 10.65 err/s: 0.00 reconn/s: 0.00
[ 440s ] thds: 48 tps: 7352.34 qps: 29408.77 (r/w/o: 0.00/29408.77/0.00) lat (ms,95%): 10.27 err/s: 0.00 reconn/s: 0.00
[ 450s ] thds: 48 tps: 7356.35 qps: 29424.11 (r/w/o: 0.00/29424.11/0.00) lat (ms,95%): 10.46 err/s: 0.00 reconn/s: 0.00
[ 460s ] thds: 48 tps: 7269.48 qps: 29079.13 (r/w/o: 0.00/29079.13/0.00) lat (ms,95%): 10.65 err/s: 0.00 reconn/s: 0.00
[ 470s ] thds: 48 tps: 7295.22 qps: 29179.68 (r/w/o: 0.00/29179.58/0.10) lat (ms,95%): 10.65 err/s: 0.00 reconn/s: 0.00
[ 480s ] thds: 48 tps: 7258.87 qps: 29037.09 (r/w/o: 0.00/29036.89/0.20) lat (ms,95%): 10.65 err/s: 0.00 reconn/s: 0.00
[ 490s ] thds: 48 tps: 7312.73 qps: 29248.64 (r/w/o: 0.00/29248.64/0.00) lat (ms,95%): 10.65 err/s: 0.00 reconn/s: 0.00
[ 500s ] thds: 48 tps: 7351.52 qps: 29408.80 (r/w/o: 0.00/29408.80/0.00) lat (ms,95%): 10.65 err/s: 0.00 reconn/s: 0.00
[ 510s ] thds: 48 tps: 8298.04 qps: 33191.17 (r/w/o: 0.00/33190.97/0.20) lat (ms,95%): 8.43 err/s: 0.00 reconn/s: 0.00
[ 520s ] thds: 48 tps: 8386.27 qps: 33543.08 (r/w/o: 0.00/33543.08/0.00) lat (ms,95%): 8.58 err/s: 0.00 reconn/s: 0.00
[ 530s ] thds: 48 tps: 8379.00 qps: 33516.81 (r/w/o: 0.00/33516.71/0.10) lat (ms,95%): 8.43 err/s: 0.00 reconn/s: 0.00
[ 540s ] thds: 48 tps: 8340.53 qps: 33363.82 (r/w/o: 0.00/33363.82/0.00) lat (ms,95%): 8.74 err/s: 0.00 reconn/s: 0.00
[ 550s ] thds: 48 tps: 8401.08 qps: 33603.44 (r/w/o: 0.00/33603.44/0.00) lat (ms,95%): 8.58 err/s: 0.00 reconn/s: 0.00
[ 560s ] thds: 48 tps: 8290.48 qps: 33163.43 (r/w/o: 0.00/33163.13/0.30) lat (ms,95%): 8.74 err/s: 0.00 reconn/s: 0.00
[ 570s ] thds: 48 tps: 8263.53 qps: 33051.53 (r/w/o: 0.00/33051.43/0.10) lat (ms,95%): 8.58 err/s: 0.00 reconn/s: 0.00

可以看到从 510s 之后,写入的 QPS 发生了比较明显的变化,提升了约 4000,大概 13%。

而对比一下改之前和改之后的 CPU 使用情况:

修改前的 top
修改前的 top
修改后的 top
修改后的 top

可以看到,绑定了 CPU 之后,0 和 1 号线程的负载情况发生了明显的变化,说明改动已经即时生效,两个内部线程独占了两个 CPU 核心。

总结一下

当然,这个写入的问题在之后的版本中应该会有官方修复方案,但是从这个简单的写入性能优化中,也可以看到资源组的实际效果还是比较明显的,当存在一些特殊需求,需要倾斜一部分资源的时候,合理的使用资源组这个功能可以最大限度的保障业务的稳定与高效。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 资源组
    • 简介
      • 如何使用
      • 写入性能优化
        • 简介
          • 测试一下
          • 总结一下
          相关产品与服务
          云数据库 MySQL
          腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档