1. ProxySQL中的库

使用ProxySQLAdmin管理接口连上ProxySQL , 可查看ProxySQL拥有的库。

root@ubuntu2204:~# mysql -uadmin -padmin -h127.0.0.1 -P6032 --prompt 'admin> '
​
admin> show databases;
+-----+---------------+-------------------------------------+
| seq | name          | file                                |
+-----+---------------+-------------------------------------+
| 0   | main          |                                     |
| 2   | disk          | /var/lib/proxysql/proxysql.db       |
| 3   | stats         |                                     |
| 4   | monitor       |                                     |
| 5   | stats_history | /var/lib/proxysql/proxysql_stats.db |
+-----+---------------+-------------------------------------+
5 rows in set (0.00 sec)
​

其中 :

  • main库是ProxySQL最主要的库 , 是需要修改配置时使用的库 , 它其实是一个内存数据库系统。所以 , 修改main库中的配置后 , 必须将其持久化到disk上才能永久保存。

  • disk库是磁盘数据库 , 该数据库结构和内存数据库完全一致。当持久化内存数据库中的配置时 , 其实就是写入到disk库中。磁盘数据库的默认路径为$DATADIR/proxysql.db

  • stats库是统计信息库。这个库中的数据一般是在检索其内数据时临时填充的 , 它保存在内存中。因为没有相关的配置项 , 所以无需持久化。

  • monitor库是监控后端MySQL节点相关的库 , 该库中只有几个log类的表 , 监控模块收集到的监控信息全都存放到对应的log表中。

  • stats_history库是1.4.4版新增的库 , 用于存放历史统计数据。默认路径为$DATADIR/proxysql_stats.db

ProxySQL内部使用的是SQLite3数据库 , 无论是内存数据库还是磁盘数据库 , 都是通过SQLite3引擎进行解析、操作的。它和MySQL的语法可能稍有不同 , 但ProxySQL会对不兼容的语法自动进行调整 , 最大程度上保证MySQL语句的有效率。

上面描述main库的时候 , 只是说了内存数据库需要持久化到disk库才能永久保存配置。但实际上 , 修改了main库中的配置后 , 并不会立即生效 , 它还需要loadruntime的数据结构中才生效 , 只有在runtime数据结构中的配置才是对ProxySQL当前有效的配置。请看下面的"多层配置系统"

2.ProxySQL的多层配置系统

ProxySQL的配置系统非常强大 , 它能在线修改几乎所有配置(仅有的两个需要重启才能生效的变量mysql-threadsmysql-stacksize) , 并在线生效、持久化保存。这得益于它采用的多层配置系统。

多层配置系统结构如下:

       +-------------------------+
       |         RUNTIME         |
       +-------------------------+
              /|\          |
               |           |
           [1] |       [2] |
               |          \|/
       +-------------------------+
       |         MEMORY          |
       +-------------------------+ _
              /|\          |      |\
               |           |        \
           [3] |       [4] |         \ [5]
               |          \|/         \
       +-------------------------+  +---------------+
       |          DISK           |  |  CONFIG FILE  |
       +-------------------------+  +---------------+
​

解释下这个3层的配置系统。

最底层的是disk库和config file。这里需要注意 , 这里的config file就是传统的配置文件 , 默认为/etc/proxysql.cnf , ProxySQL启动时 , 主要是从disk库中读取配置加载到内存并最终加载到runtime生效 , 只有极少的几个特定配置内容是从config file中加载的 , 除非是第一次初始化ProxySQL运行环境(或者disk库为空)。

中间层的是memory , 表示的是内存数据库 , 其实就是main库。通过管理接口修改的所有配置 , 都保存在内存数据库(main)中。当ProxySQL重启或者崩溃时 , 这个内存数据库中的数据会丢失 , 所以需要savedisk库中。

最上层的是runtime , 它是ProxySQL有关线程运行时读取的数据结构。换句话说 , 该数据结构中的配置都是已生效的配置。所以 , 修改了main库中的配置后 , 必须loadruntime数据结构中才能使其生效。

在上面的多层配置系统图中 , 标注了[1][2][3][4][5]的序号。每个序号都有两个操作方向from/to b , 其实只是所站角度不同而已。以下是各序号对应的操作 :

[1] :将内存数据库中的配置加载到RUNTIME数据结构中
        LOAD XXX FROM MEMORY
        LOAD XXX TO RUNTIME
​
[2] :将RUNTIME数据结构中的配置持久化到内存数据库中
        SAVE XXX FROM RUNTIME
        SAVE XXX TO MEMORY
​
[3] :将磁盘数据库中的配置加载到内存数据库中
        LOAD XXX FROM DISK
        LOAD XXX TO MEMORY
​
[4] :将内存数据库中的配置持久化到磁盘数据库中
        SAVE XXX FROM MEMORY
        SAVE XXX TO DISK
​
[5] :从传统配置文件中读取配置加载到内存数据库中
        LOAD XXX FROM CONFIG
​

DISK/MEMORY/RUNTIME/CONFIG可以缩写,只要能识别即可。例如MEMORY可以缩写为MEMruntime可以缩写为run

另外,上面的XXX是什么?这表示要加载/保存的是哪类配置。目前的ProxySQL支持以下几种:

  • mysql users

  • mysql servers

  • mysql variables

  • mysql query rules

  • admin variables

  • scheduler

  • proxysql_servers:目前ProxySQL集群功能还处于实验阶段,所以该类配置不应该去使用。

这些从main库或disk库中就可以查看到。

admin> show tables from disk;
+------------------------------------+
| tables                             |
+------------------------------------+
| global_variables                   |  # (1)
| mysql_collations                   |  # (N)
| mysql_group_replication_hostgroups |  # (2)
| mysql_query_rules                  |  # (3)
| mysql_query_rules_fast_routing     |  # (4)
| mysql_replication_hostgroups       |  # (5)
| mysql_servers                      |  # (6)
| mysql_users                        |  # (7)
| proxysql_servers                   |  # (8)
| scheduler                          |  # (9)
+------------------------------------+
​
  • (1)中包含两类变量,以amdin-开头的表示admin variables,以mysql-开头的表示mysql variables。修改哪类变量,前文的XXX就代表哪类。

  • (2,5,6)对应的都是mysql servers

  • (3,4)对应的是mysql query rules

  • (7)对应的mysql users

  • (9)对应的scheduler

  • (N)只是一张表,保存的是ProxySQL支持的字符集和排序规则,它是不用修改的。

  • (8)是ProxySQL的集群配置表,该功能目前还处于实验阶段。如果想要配置该功能,则load/save proxysql_servers to/from ...

733013-20180708181415362-333439073

以下是几个示例:注意,几乎所有配置都是在admin管理接口上修改的,这也是建议的配置方式。

  1. ProxySQLmysql_servers表中添加了一个后端节点。

    load mysql servers to runtime;    # 加载到runtime使该节点的配置生效
    save mysql servers to disk;     # 将该节点的配置持久化到磁盘数据库中

    上面两句和下面两句是等价的,只是操作方向不同(还使用了缩写):

    load mysql servers from mem;
    save mysql servers from mem;
  2. ProxySQLmysql_users表中添加了用于发送、处理SQL语句的用户。

    load mysql users to runtime;
    save mysql users to disk;
  3. 修改了以admin-开头的变量。

    load admin variables to runtime;
    save admin variables to disk;

新版本数据的表格名以及对应的item

admin>  show tables from disk;
+--------------------------------------------+
| tables                                     |
+--------------------------------------------+
| global_settings                            |
| global_variables                           |
| mysql_aws_aurora_hostgroups                |
| mysql_collations                           |
| mysql_firewall_whitelist_rules             |
| mysql_firewall_whitelist_sqli_fingerprints |
| mysql_firewall_whitelist_users             |
| mysql_galera_hostgroups                    |
| mysql_group_replication_hostgroups         |
| mysql_hostgroup_attributes                 |
| mysql_query_rules                          |
| mysql_query_rules_fast_routing             |
| mysql_replication_hostgroups               |
| mysql_servers                              |
| mysql_servers_ssl_params                   |
| mysql_users                                |
| proxysql_servers                           |
| restapi_routes                             |
| scheduler                                  |
+--------------------------------------------+
19 rows in set (0.02 sec)

表格名

对应的 item 名称

功能说明

global_settings

ADMIN VARIABLES

全局管理配置 ( 如管理接口账号 )

global_variables

MYSQL VARIABLES

MySQL 相关运行时变量 ( 如连接池大小 )

mysql_aws_aurora_hostgroups

AWS AURORA HOSTGROUPS

AWS Aurora 集群读写分离配置

mysql_collations

无直接命令

字符集和校对规则 ( 自动加载,无需手动操作 )

mysql_firewall_whitelist_rules

MYSQL FIREWALL

SQL 防火墙白名单规则

mysql_firewall_whitelist_sqli_fingerprints

MYSQL FIREWALL

SQL 注入指纹规则

mysql_firewall_whitelist_users

MYSQL FIREWALL

用户与白名单规则的关联

mysql_galera_hostgroups

GALERA HOSTGROUPS

Galera 集群读写分离配置

mysql_group_replication_hostgroups

GROUP REPLICATION HOSTGROUPS

MySQL Group Replication 集群配置

mysql_hostgroup_attributes

MYSQL HOSTGROUP ATTRIBUTES

主机组的附加属性 ( 如最大连接数 )

mysql_query_rules

MYSQL QUERY RULES

查询路由规则

mysql_query_rules_fast_routing

MYSQL QUERY RULES

快速路由规则缓存 ( 自动关联主规则表 )

mysql_replication_hostgroups

MYSQL REPLICATION HOSTGROUPS

传统主从复制集群配置

mysql_servers

MYSQL SERVERS

后端 MySQL 实例列表

mysql_servers_ssl_params

MYSQL SERVERS SSL

MySQL 实例的 SSL 连接参数

mysql_users

MYSQL USERS

ProxySQL 管理的用户凭据

proxysql_servers

PROXYSQL SERVERS

ProxySQL 集群节点配置

restapi_routes

RESTAPI ROUTES

REST API 自定义路由配置

scheduler

SCHEDULER

定时任务配置 ( 如定期执行脚本 )

3. 启动ProxySQL时如何加载配置

如果ProxySQL是刚安装的,或者磁盘数据库文件为空(甚至不存在),或者启动ProxySQL时使用了选项--initial,这几种情况启动ProxySQL时,都会从传统配置文件config file中读取配置加载到内存数据库,并自动loadruntime数据结构、save到磁盘数据库,这是初始化ProxySQL运行环境的过程。

如果不是第一次启动ProxySQL,由于已经存在磁盘数据库文件,这时ProxySQL会从磁盘数据库中读取几乎所有的配置(即使传统配置文件中配置了某项,也不会去解析),但有3项是必须从传统配置文件中读取的。这3项是:

  • datadirProxySQL启动时,必须从配置文件中确定它的数据目录,因为磁盘数据库文件、日志以及其它一些文件是存放在数据目录下的。如果使用/etc/init.d/proxysql管理ProxySQL,则除了修改/etc/proxysql.cnfdatadir,还需要修改该脚本中的datadir

  • restart_on_missing_heartbeatsMySQL线程丢失多少次心跳,就会杀掉这个线程并重启它。默认值为10

  • execute_on_exit_failure:如果设置了该变量,ProxySQL父进程将在每次ProxySQL崩溃的时候执行已经定义好的脚本。建议使用它来生成一些崩溃时的警告和日志。注意,ProxySQL的重启速度可能只有几毫秒,因此很多其它的监控工具可能无法探测到ProxySQL的一次普通故障,此时可使用该变量。

4.关于传统配置文件

传统配置文件默认路径为/etc/proxysql.cnf,也可以在二进制程序proxysql上使用-c--config来手动指定配置文件。

ProxySQL的传统配置文件示例如下:浏览下即可,几乎不需要手动去配置proxysql.cnf

datadir="/var/lib/proxysql"

admin_variables=
{
        admin_credentials="admin:admin"
#       mysql_ifaces="127.0.0.1:6032;/tmp/proxysql_admin.sock"
        mysql_ifaces="0.0.0.0:6032"
#       refresh_interval=2000
#       debug=true
}

mysql_variables=
{
        threads=4
        max_connections=2048
        default_query_delay=0
        default_query_timeout=36000000
        have_compress=true
        poll_timeout=2000
#       interfaces="0.0.0.0:6033;/tmp/proxysql.sock"
        interfaces="0.0.0.0:6033"
        default_schema="information_schema"
        stacksize=1048576
        server_version="5.5.30"
        connect_timeout_server=3000
# make sure to configure monitor username and password
        monitor_username="monitor"
        monitor_password="monitor"
        monitor_history=600000
        monitor_connect_interval=60000
        monitor_ping_interval=10000
        monitor_read_only_interval=1500
        monitor_read_only_timeout=500
        ping_interval_server_msec=120000
        ping_timeout_server=500
        commands_stats=true
        sessions_sort=true
        connect_retries_on_failure=10
}


# defines all the MySQL servers
mysql_servers =
(
# {
#   address = "127.0.0.1" # no default, required . If port is 0 , address is interpred as a Unix Socket Domain
#   port = 3306           # no default, required . If port is 0 , address is interpred as a Unix Socket Domain
#   hostgroup = 0         # no default, required
#   status = "ONLINE"     # default: ONLINE
#   weight = 1            # default: 1
#   compression = 0       # default: 0
#   max_replication_lag = 10  # default 0 . If greater than 0 and replication lag passes such threshold, the server is shunned
# },
#       {
#               address = "/var/lib/mysql/mysql.sock"
#               port = 0
#               hostgroup = 0
#       },
#       {
#               address="127.0.0.1"
#               port=21891
#               hostgroup=0
#               max_connections=200
#       },
#       { address="127.0.0.2" , port=3306 , hostgroup=0, max_connections=5 },
#       { address="127.0.0.1" , port=21892 , hostgroup=1 },
#       { address="127.0.0.1" , port=21893 , hostgroup=1 }
#       { address="127.0.0.2" , port=3306 , hostgroup=1 },
#       { address="127.0.0.3" , port=3306 , hostgroup=1 },
#       { address="127.0.0.4" , port=3306 , hostgroup=1 },
#       { address="/var/lib/mysql/mysql.sock" , port=0 , hostgroup=1 }
)


# defines all the MySQL users
mysql_users:
(
#       {
#               username = "username" # no default , required
#               password = "password" # default: ''
#               default_hostgroup = 0 # default: 0
#               active = 1            # default: 1
#       },
#       {
#               username = "root"
#               password = ""
#               default_hostgroup = 0
#               max_connections=1000
#               default_schema="test"
#               active = 1
#       },
#       { username = "user1" , password = "password" , default_hostgroup = 0 , active = 0 }
)



#defines MySQL Query Rules
mysql_query_rules:
(
#       {
#               rule_id=1
#               active=1
#               match_pattern="^SELECT .* FOR UPDATE$"
#               destination_hostgroup=0
#               apply=1
#       },
#       {
#               rule_id=2
#               active=1
#               match_pattern="^SELECT"
#               destination_hostgroup=1
#               apply=1
#       }
)

scheduler=
(
#  {
#    id=1
#    active=0
#    interval_ms=10000
#    filename="/var/lib/proxysql/proxysql_galera_checker.sh"
#    arg1="0"
#    arg2="0"
#    arg3="0"
#    arg4="1"
#    arg5="/var/lib/proxysql/proxysql_galera_checker.log"
#  }
)


mysql_replication_hostgroups=
(
#        {
#                writer_hostgroup=30
#                reader_hostgroup=40
#                comment="test repl 1"
#       },
#       {
#                writer_hostgroup=50
#                reader_hostgroup=60
#                comment="test repl 2"
#        }
)


参考链接

MySQL中间件之ProxySQL(4):多层配置系统 - 骏马金龙 - 博客园


熊熊