暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL Resource Group

00后DBA实录 2024-12-28
54

前言

自 2024/10/19 建公众号以来过了 2 个月的时间,公众号的关注来到了 200+,非常感谢大家的关注。在我的公众号的发消息界面点击 “加我滴群” 即可获取我自己建的群的二维码,里面不少大佬,欢迎来提问交流学习。

前不久讲了 Rewriter Query Rewrite Plugin ,之前有小伙伴问 MySQL 能不能限制 SQL 的资源占用,MySQL 确实支持这样一个功能 Resource Group,但是好像不咋用,也没啥名气,我就来讲讲这个怎么用吧。

什么是资源组

我们知道 numactl 可以对进程绑定 CPU 核心数,但是它的作用域是限定进程的,Resource Group 类似于 numactl 管控 CPU 核心数,也是把 CPU 组在一起再管控,只不过它的作用域缩小到了线程。

CPU 时间是一种可管理的资源,由 “virtual CPU” 概念表示,该术语包括 CPU 核心、超线程、硬件线程等。服务器在启动时确定可用的虚拟 CPU 数量,我们将这些 CPU 与资源组关联并将线程分配给资源组。

Resource Group 的配置基于本地操作系统进行,所以分布于不同机器的主从需要单独配置资源组,且资源组语句不会写入 Binlog。

操作系统

设置了 CAP_SYS_NICE
 功能的 Linux 操作系统可用。

Windows 可用

在 macOS 平台上,资源组不可用

在 FreeBSD 和 Solaris 平台上,资源组的线程优先级设置会被忽略(实际上,所有线程都以优先级 0
 运行。)

Linux 比较常用,我这里只配置 Linux 上的。

配置 CAP_SYS_NICE

因为 Resource Group 依赖 Linux 内核的 CAP_SYS_NICE
 功能,所以这里需要配置给 mysqld
 开启该功能。

sudo setcap cap_sys_nice+ep application/mysql_8_3306/bin/mysqld

使用该命令查看是否配置完成

[root@localhost ~]# getcap application/mysql_8_3306/bin/mysqld
/application/mysql_8_3306/bin/mysqld = cap_sys_nice+ep

重启启动即可

mysqld_safe --defaults-file=/etc/my.cnf

错误处理

systemd
 管理的 mysqld
 可能报错找不到 libcrypto.so.1.1

2024-12-27T16:26:12.686054Z mysqld_safe Starting mysqld daemon with databases from /data/mysql_8_3306/application/mysql_8_3306/bin/mysqld: error while loading shared libraries: libcrypto.so.1.1: cannot open shared object fileNo such file or directory

需要配置

chown root:mysql application/mysql_8_3306/bin/mysqld
chmod 0750 application/mysql_8_3306/bin/mysqld

Resource Group 属性

资源组具有定义组的属性。所有属性都可以在创建组时设置。有些属性在创建时是固定的;其他属性可以在之后的任何时间进行修改。

  • 每个组都有一个名称。资源组名称是标识符,如表和列名称,组名不区分大小写。

  • 每个组都有一个类型,即 SYSTEM
     或 USER
    (对应于 FOREGROUN
     和 BACKGROUND
     )。资源组类型会影响可分配给组的优先级值范围。此属性与允许优先级的差异一起,使系统线程能够被识别,从而保护它们免于与用户线程争用 CPU 资源。

这些属性是在创建资源组时定义的,此后可以随时修改:

  • CPU 绑定(CPU Affinity
    )是资源组可以使用的 virtual CPUs
     集。亲和性可以是可用 CPU
     的任何非空子集。如果一个组没有亲和性,则可以使用所有可用 CPU。

  • 线程优先级是分配给资源组的线程的执行优先级。优先级值的范围从 -20
    (最高优先级)到 19
    (最低优先级)。系统组和用户组的默认优先级都是 0

    系统组的优先级高于用户组,确保用户线程的优先级永远不会高于系统线程:

    • 对于系统资源组,允许的优先级范围是 -20
       到 0

    • 对于用户资源组,允许的优先级范围是 0
       到 19

  • 每个组都可以启用或禁用,让管理员可以控制线程分配。线程只能分配给已启用的组。

配置 Resource Group

未配置的情况下,默认有 3 个资源组:

+---------------------+---------------------+------------------------+--------------------+-----------------+
| RESOURCE_GROUP_NAME | RESOURCE_GROUP_TYPE | RESOURCE_GROUP_ENABLED | VCPU_IDS           | THREAD_PRIORITY |
+---------------------+---------------------+------------------------+--------------------+-----------------+
| USR_default         | USER                |                      1 | 0x302D31           |               0 |
| SYS_default         | SYSTEM              |                      1 | 0x302D31           |               0 |
| SYS_internal        | SYSTEM              |                      1 | 0x302D31           |               0 |
+---------------------+---------------------+------------------------+--------------------+-----------------+

我的虚拟机分配了 0,1 的 2 个 CPU 核:

Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                2
On-line CPU(s) list:   0,1

创建语法:

CREATE RESOURCE GROUP group_name
    TYPE = {SYSTEM|USER}
    [VCPU [=] vcpu_spec [, vcpu_spec] ...]
    [THREAD_PRIORITY [=] N]
    [ENABLE|DISABLE]

vcpu_spec: {N | M - N}

TYPE
 可选  SYSTEM
 或 USER
 ,代表系统和用户

THREAD_PRIORITY
 代表资源组的线程分配优先级,默认值为 0
 ,SYSTEM
 可选 -20 to 0
 ,USER
 可选 0 to 19

ENABLE|DISABLE
 默认开启关闭

创建一个资源组 g1
 分配一个核:

create resource group g1 type=user vcpu=0 thread_priority=1 enable;

如果没有重启就去创建资源组则无法设置 thread_priority
,为不生效的结果

root@localhost [(none)] 11:50:14 > create resource group g1 type=user vcpu=0 thread_priority=1 enable;
Query OK, 0 rows affected, 1 warning (0.10 sec)

root@localhost [(none)] 11:50:15 > show warnings;
+---------+------+-------------------------------------------------------------+
| Level   | Code | Message                                                     |
+---------+------+-------------------------------------------------------------+
| Warning | 3659 | Attribute thread_priority is ignored (using default value). |
+---------+------+-------------------------------------------------------------+
1 row in set (0.00 sec)

重启后即可解决此问题

root@localhost [(none)] 11:55:56 > create resource group g1 type=user vcpu=0 thread_priority=1 enable;
Query OK, 0 rows affected (0.01 sec)

创建一个资源组 g2
 分配两个核:

create resource group g2 type=user vcpu=0,1 thread_priority=2 enable;
or
create resource group g2 type=user vcpu=0-1 thread_priority=2 enable;

可通过 information_schema.RESOURCE_GROUPS
 查看

root@localhost [(none)] 11:59:06 > select * from information_schema.RESOURCE_GROUPS;
+---------------------+---------------------+------------------------+--------------------+-----------------+
| RESOURCE_GROUP_NAME | RESOURCE_GROUP_TYPE | RESOURCE_GROUP_ENABLED | VCPU_IDS           | THREAD_PRIORITY |
+---------------------+---------------------+------------------------+--------------------+-----------------+
| USR_default         | USER                |                      1 | 0x302D31           |               0 |
| SYS_default         | SYSTEM              |                      1 | 0x302D31           |               0 |
| SYS_internal        | SYSTEM              |                      1 | 0x302D31           |               0 |
| g1                  | USER                |                      1 | 0x30               |               1 |
| g2                  | USER                |                      1 | 0x302D31           |               2 |
+---------------------+---------------------+------------------------+--------------------+-----------------+
5 rows in set (0.02 sec)

删除资源组

drop resource group g2;

修改资源组(也可以修改部分,不写不需要的部分即可保持原值。)

ALTER RESOURCE GROUP g2 vcpu=0 THREAD_PRIORITY=5 disable;

查看

root@localhost [(none)] 12:02:46 > select * from information_schema.RESOURCE_GROUPS;
+---------------------+---------------------+------------------------+--------------------+-----------------+
| RESOURCE_GROUP_NAME | RESOURCE_GROUP_TYPE | RESOURCE_GROUP_ENABLED | VCPU_IDS           | THREAD_PRIORITY |
+---------------------+---------------------+------------------------+--------------------+-----------------+
| USR_default         | USER                |                      1 | 0x302D31           |               0 |
| SYS_default         | SYSTEM              |                      1 | 0x302D31           |               0 |
| SYS_internal        | SYSTEM              |                      1 | 0x302D31           |               0 |
| g1                  | USER                |                      1 | 0x30               |               1 |
| g2                  | USER                |                      0 | 0x30               |               5 |
+---------------------+---------------------+------------------------+--------------------+-----------------+
5 rows in set (0.01 sec)

分配线程到资源组有两种方法:

  • SET RESOURCE GROUP FOR thread_id
  • 配置 hint
     ,/*+ RESOURCE_GROUP(g2) */

可通过 performance_schema.threads
 查看 thread_id
 和 RESOURCE_GROUP

root@localhost [(none)] 12:06:44 > select * from performance_schema.threads where PROCESSLIST_ID=9\G
*************************** 1. row ***************************
            THREAD_ID: 47
                 NAMEthread/sql/one_connection
                 TYPE: FOREGROUND
       PROCESSLIST_ID: 9
     PROCESSLIST_USER: root
     PROCESSLIST_HOST: localhost
       PROCESSLIST_DB: NULL
  PROCESSLIST_COMMAND: Query
     PROCESSLIST_TIME: 0
    PROCESSLIST_STATE: executing
     PROCESSLIST_INFO: select * from performance_schema.threads where PROCESSLIST_ID=9
     PARENT_THREAD_ID: NULL
                 ROLENULL
         INSTRUMENTED: YES
              HISTORY: YES
      CONNECTION_TYPE: Socket
         THREAD_OS_ID: 864
       RESOURCE_GROUP: USR_default
     EXECUTION_ENGINE: PRIMARY
    CONTROLLED_MEMORY: 46176
MAX_CONTROLLED_MEMORY: 100032
         TOTAL_MEMORY: 296828
     MAX_TOTAL_MEMORY: 309164
1 row in set (0.01 sec)

然后使用 SET
 分配

set resource group g1 for 47;

再次查看可以看到 RESOURCE_GROUP
 变成了 g1

root@localhost [(none)] 12:08:49 > select * from performance_schema.threads where PROCESSLIST_ID=9\G
*************************** 1. row ***************************
            THREAD_ID: 47
                 NAMEthread/sql/one_connection
                 TYPE: FOREGROUND
       PROCESSLIST_ID: 9
     PROCESSLIST_USER: root
     PROCESSLIST_HOST: localhost
       PROCESSLIST_DB: NULL
  PROCESSLIST_COMMAND: Query
     PROCESSLIST_TIME: 0
    PROCESSLIST_STATE: executing
     PROCESSLIST_INFO: select * from performance_schema.threads where PROCESSLIST_ID=9
     PARENT_THREAD_ID: NULL
                 ROLENULL
         INSTRUMENTED: YES
              HISTORY: YES
      CONNECTION_TYPE: Socket
         THREAD_OS_ID: 864
       RESOURCE_GROUP: g1
     EXECUTION_ENGINE: PRIMARY
    CONTROLLED_MEMORY: 39056
MAX_CONTROLLED_MEMORY: 100032
         TOTAL_MEMORY: 289796
     MAX_TOTAL_MEMORY: 309164
1 row in set (0.00 sec)

再开一个窗口发出

select /*+ RESOURCE_GROUP(g1) */ *,sleep(10from ddl.ddl;

然后就可以看见新开的连接的 RESOURCE_GROUP
 为 g1

root@localhost [(none)] 12:11:25 > select * from performance_schema.threads where PROCESSLIST_ID=10\G
*************************** 1. row ***************************
            THREAD_ID: 48
                 NAMEthread/sql/one_connection
                 TYPE: FOREGROUND
       PROCESSLIST_ID: 10
     PROCESSLIST_USER: root
     PROCESSLIST_HOST: localhost
       PROCESSLIST_DB: NULL
  PROCESSLIST_COMMAND: Query
     PROCESSLIST_TIME: 3
    PROCESSLIST_STATE: User sleep
     PROCESSLIST_INFO: select /*+ RESOURCE_GROUP(g1) */ *,sleep(10from ddl.ddl
     PARENT_THREAD_ID: 1
                 ROLENULL
         INSTRUMENTED: YES
              HISTORY: YES
      CONNECTION_TYPE: Socket
         THREAD_OS_ID: 26504
       RESOURCE_GROUP: g1
     EXECUTION_ENGINE: PRIMARY
    CONTROLLED_MEMORY: 39296
MAX_CONTROLLED_MEMORY: 46416
         TOTAL_MEMORY: 83711
     MAX_TOTAL_MEMORY: 90325
1 row in set (0.00 sec)


执行结束变回原组

root@localhost [(none)] 12:13:51 > select * from performance_schema.threads where PROCESSLIST_ID=10\G
*************************** 1. row ***************************
            THREAD_ID: 48
                 NAMEthread/sql/one_connection
                 TYPE: FOREGROUND
       PROCESSLIST_ID: 10
     PROCESSLIST_USER: root
     PROCESSLIST_HOST: localhost
       PROCESSLIST_DB: NULL
  PROCESSLIST_COMMAND: Sleep
     PROCESSLIST_TIME: 141
    PROCESSLIST_STATE: NULL
     PROCESSLIST_INFO: NULL
     PARENT_THREAD_ID: 1
                 ROLENULL
         INSTRUMENTED: YES
              HISTORY: YES
      CONNECTION_TYPE: Socket
         THREAD_OS_ID: 26504
       RESOURCE_GROUP: USR_default
     EXECUTION_ENGINE: PRIMARY
    CONTROLLED_MEMORY: 18720
MAX_CONTROLLED_MEMORY: 46416
         TOTAL_MEMORY: 63071
     MAX_TOTAL_MEMORY: 90325
1 row in set (0.00 sec)

总结

Resource Group 类似于 numactl 管控 CPU 核心数,也是把 CPU 组在一起再管控,只不过它的作用域缩小到了线程。

可以使用:

  • 会话级别的 set
  • 语句级别 hint
     配置加入资源组

往期回顾


感谢阅读!关注我获取更多精彩内容。


文章转载自00后DBA实录,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论