ProxySQL 集成指南

本文简要介绍 ProxySQL,描述如何在开发环境生产环境中将 ProxySQL 与 TiDB 集成,并通过查询规则的场景展示集成的主要优势。

关于 TiDB 和 ProxySQL 的更多信息,请参考以下文档:

什么是 ProxySQL?

ProxySQL 是一个高性能的开源 SQL 代理。它具有灵活的架构,可以通过多种方式部署,适合各类使用场景。例如,ProxySQL 可以通过缓存频繁访问的数据来提高性能。

ProxySQL 的设计目标是快速、高效且易于使用。它完全兼容 MySQL,并支持高质量 SQL 代理的所有功能。此外,ProxySQL 还提供了许多独特功能,使其成为各种应用程序的理想选择。

为什么集成 ProxySQL?

  • ProxySQL 可以通过降低与 TiDB 交互的延迟来提升应用程序性能。无论你构建什么,无论是使用 Lambda 等无服务器函数的可扩展应用程序(其工作负载不确定并且可能激增),还是构建执行大量数据查询的应用程序,都可以利用 ProxySQL 的强大功能(例如连接池缓存常用查询)。
  • ProxySQL 可以作为应用程序安全防护的附加层,使用查询规则防止 SQL 漏洞(例如 SQL 注入)。
  • 由于 ProxySQLTiDB 都是开源项目,你可以享受到零供应商锁定的好处。

部署架构

将 ProxySQL 与 TiDB 集成的最直接方式是在应用层和 TiDB 之间添加 ProxySQL 作为独立中介。但是,这种方式无法保证可扩展性和容错性,而且可能因为网络跳转而增加延迟。为避免这些问题,一种替代部署架构是将 ProxySQL 作为附属容器部署,如下图所示:

proxysql-client-side-tidb-cloud

开发环境

本节介绍如何在开发环境中将 TiDB 与 ProxySQL 集成。在满足前提条件的情况下,你可以根据 TiDB 集群类型选择以下选项之一开始集成 ProxySQL:

前提条件

根据选择的方案,你可能需要以下依赖:

你可以按照下面的说明进行安装:

  • macOS
  • CentOS
  • Windows
  1. 下载并启动 Docker,其中 Docker Desktop 已包含 Docker Compose。

  2. 运行以下命令安装 Python 和 mysql-client

    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" brew install python mysql-client
curl -fsSL https://get.docker.com | bash -s docker yum install -y git python39 docker-ce docker-ce-cli containerd.io docker-compose-plugin mysql systemctl start docker
  • 下载并安装 Git。

    1. Download for Windows 页面下载 64-bit Git for Windows Setup 安装程序。

    2. 按照安装向导提示安装 Git。你可以多次点击 Next 使用默认的安装设置。

      proxysql-windows-git-install

  • 下载并安装 MySQL Shell。

    1. MySQL Community Server Download 页面下载 MySQL Installer 的 ZIP 文件。

    2. 解压文件,并在 bin 文件夹中找到 mysql.exe。你需要将该 bin 文件夹的路径添加到系统变量中,并在 Git Bash 中将其设置到 PATH 变量中。

      echo 'export PATH="(your bin folder)":$PATH' >>~/.bash_profile source ~/.bash_profile

      例如:

      echo 'export PATH="/c/Program Files (x86)/mysql-8.0.31-winx64/bin":$PATH' >>~/.bash_profile source ~/.bash_profile
  • 下载并安装 Docker。

    1. Docker Download 页面下载 Docker Desktop 安装程序。

    2. 双击安装程序运行。安装完成后,会提示你重新启动。

      proxysql-windows-docker-install

  • Python Download 页面下载最新版的 Python 3 安装程序并运行。

选项 1: 集成 TiDB Cloud 与 ProxySQL

在这个集成中,你将使用 ProxySQL Docker 镜像以及 TiDB Serverless 集群。下面的步骤将在端口 16033 上设置 ProxySQL,请确保此端口可用。

步骤 1. 创建一个 TiDB Serverless 集群

  1. 参考创建一个 TiDB Serverless 集群文档。记住为集群设置的 root 密码。

  2. 获取集群的 hostnameportusername 供后续使用。

    1. Clusters 页面,点击你的集群名称,进入集群概览页面。
    2. 在集群概览页面的 Connection 面板中,复制 EndpointPortUser 字段,其中 Endpoint 是集群的 hostname

步骤 2. 生成 ProxySQL 配置文件

  1. 克隆 TiDB 和 ProxySQL 的集成示例代码仓库 tidb-proxysql-integration

    • macOS
    • CentOS
    • Windows (Git Bash)
    git clone https://github.com/pingcap-inc/tidb-proxysql-integration.git
    git clone https://github.com/pingcap-inc/tidb-proxysql-integration.git
    git clone https://github.com/pingcap-inc/tidb-proxysql-integration.git
  2. 进入 tidb-cloud-connect 目录:

    • macOS
    • CentOS
    • Windows (Git Bash)
    cd tidb-proxysql-integration/example/tidb-cloud-connect
    cd tidb-proxysql-integration/example/tidb-cloud-connect
    cd tidb-proxysql-integration/example/tidb-cloud-connect
  3. 运行 proxysql-config.py 生成 ProxySQL 配置文件:

    • macOS
    • CentOS
    • Windows (Git Bash)
    python3 proxysql-config.py
    python3 proxysql-config.py
    python proxysql-config.py

    当出现提示时,输入集群的 Endpoint 作为 Serverless Tier Host,然后输入集群的 PortUser

    下面是一个输出示例。可以看到,在当前的 tidb-cloud-connect 目录下生成了三个配置文件。

    [Begin] generating configuration files.. tidb-cloud-connect.cnf generated successfully. proxysql-prepare.sql generated successfully. proxysql-connect.py generated successfully. [End] all files generated successfully and placed in the current folder.

步骤 3. 配置 ProxySQL

  1. 启动 Docker。如果 Docker 已经启动,请跳过此步骤:

    • macOS
    • CentOS
    • Windows

    双击已安装的 Docker 的图标来启动它。

    systemctl start docker

    双击已安装的 Docker 的图标来启动它。

  2. 拉取 ProxySQL 镜像,并在后台启动一个 ProxySQL 容器:

    • macOS
    • CentOS
    • Windows (Git Bash)
    docker compose up -d
    docker compose up -d
    docker compose up -d
  3. 运行以下命令集成 ProxySQL,该命令会在 ProxySQL Admin Interface 内执行 proxysql-prepare.sql

    • macOS
    • CentOS
    • Windows (Git Bash)
    docker compose exec proxysql sh -c "mysql -uadmin -padmin -h127.0.0.1 -P6032 < ./proxysql-prepare.sql"
    docker compose exec proxysql sh -c "mysql -uadmin -padmin -h127.0.0.1 -P6032 < ./proxysql-prepare.sql"
    docker compose exec proxysql sh -c "mysql -uadmin -padmin -h127.0.0.1 -P6032 < ./proxysql-prepare.sql"

    下面是一个输出示例。输出中显示集群的主机名,这意味着 ProxySQL 和 TiDB Serverless 集群之间的连接建立成功。

    *************************** 1. row *************************** hostgroup_id: 0 hostname: gateway01.us-west-2.prod.aws.tidbcloud.com port: 4000 gtid_port: 0 status: ONLINE weight: 1 compression: 0 max_connections: 1000 max_replication_lag: 0 use_ssl: 1 max_latency_ms: 0 comment:

步骤 4. 通过 ProxySQL 连接到 TiDB 集群

  1. 运行 proxysql-connect.py 连接到你的 TiDB 集群。该脚本将自动启动 MySQL 客户端并使用你在步骤 2 中指定的用户名和密码进行连接。

    • macOS
    • CentOS
    • Windows (Git Bash)
    python3 proxysql-connect.py
    python3 proxysql-connect.py
    python proxysql-connect.py
  2. 连接 TiDB 集群后,可以使用以下 SQL 语句验证连接:

    SELECT VERSION();

    如果输出了 TiDB 的版本信息,则表示你已经成功通过 ProxySQL 连接到 TiDB Serverless 集群。如需退出 MySQL 客户端,输入 quit 并按下 Enter 键。

  3. 要停止和删除容器,并返回上一个目录,运行以下命令:

    • macOS
    • CentOS
    • Windows (Git Bash)
    docker compose down cd -
    docker compose down cd -
    docker compose down cd -

选项 2: 集成本地部署的 TiDB 与 ProxySQL

在这个集成中,你将使用 TiDBProxySQL 的 Docker 镜像设置环境。你也可以尝试其他方式安装 TiDB

下面的步骤将在端口 60334000 上分别设置 ProxySQL 和 TiDB,请确保这些端口可用。

  1. 启动 Docker。如果 Docker 已经启动,请跳过此步骤:

    • macOS
    • CentOS
    • Windows

    双击已安装的 Docker 的图标来启动它。

    systemctl start docker

    双击已安装的 Docker 的图标来启动它。

  2. 克隆 TiDB 和 ProxySQL 的集成示例代码仓库 pingcap-inc/tidb-proxysql-integration

    • macOS
    • CentOS
    • Windows (Git Bash)
    git clone https://github.com/pingcap-inc/tidb-proxysql-integration.git
    git clone https://github.com/pingcap-inc/tidb-proxysql-integration.git
    git clone https://github.com/pingcap-inc/tidb-proxysql-integration.git
  3. 拉取 ProxySQL 和 TiDB 的最新镜像:

    • macOS
    • CentOS
    • Windows (Git Bash)
    cd tidb-proxysql-integration && docker compose pull
    cd tidb-proxysql-integration && docker compose pull
    cd tidb-proxysql-integration && docker compose pull
  4. 使用 TiDB 和 ProxySQL 容器启动一个集成环境:

    • macOS
    • CentOS
    • Windows (Git Bash)
    docker compose up -d
    docker compose up -d
    docker compose up -d

    你可以使用 root 用户名及空密码登录到 ProxySQL 的 6033 端口。

  5. 通过 ProxySQL 连接到 TiDB:

    • macOS
    • CentOS
    • Windows (Git Bash)
    mysql -u root -h 127.0.0.1 -P 6033
    mysql -u root -h 127.0.0.1 -P 6033
    mysql -u root -h 127.0.0.1 -P 6033
  6. 连接 TiDB 集群后,可以使用以下 SQL 语句验证连接:

    SELECT VERSION();

    如果输出了 TiDB 的版本信息,则表示你已经成功通过 ProxySQL 连接到 TiDB 集群。

  7. 要停止和删除容器,并返回上一个目录,运行以下命令:

    • macOS
    • CentOS
    • Windows (Git Bash)
    docker compose down cd -
    docker compose down cd -
    docker compose down cd -

生产环境

对于生产环境,建议直接使用 TiDB Cloud 以获得完全托管的体验。

前提条件

下载并安装一个 MySQL 客户端。例如,MySQL Shell

基于 CentOS 集成 TiDB Cloud 与 ProxySQL

你可以在不同的平台上安装 ProxySQL,下面以 CentOS 为例进行说明。

关于 ProxySQL 支持的平台和版本要求的完整列表,见 ProxySQL 文档

步骤 1. 创建一个 TiDB Dedicated 集群

具体步骤请参考创建一个 TiDB Dedicated 集群

步骤 2. 安装 ProxySQL

  1. 将 ProxySQL 添加到 YUM 仓库:

    cat > /etc/yum.repos.d/proxysql.repo << EOF [proxysql] name=ProxySQL YUM repository baseurl=https://repo.proxysql.com/ProxySQL/proxysql-2.4.x/centos/\$releasever gpgcheck=1 gpgkey=https://repo.proxysql.com/ProxySQL/proxysql-2.4.x/repo_pub_key EOF
  2. 安装 ProxySQL:

    yum install -y proxysql
  3. 启动 ProxySQL:

    systemctl start proxysql

要了解更多关于 ProxySQL 支持的平台及其安装方法,参考 ProxySQL READMEProxySQL 安装文档

步骤 3. 配置 ProxySQL

为了使用 ProxySQL 作为 TiDB 的代理,你需要配置 ProxySQL。你可以在 ProxySQL Admin Interface 中执行 SQL 语句(推荐)或使用配置文件进行配置。

选项 1: 使用 Admin Interface 配置 ProxySQL
  1. 使用标准的 ProxySQL Admin Interface 更新 ProxySQL 的配置。你可以通过任何 MySQL 命令行客户端访问(默认端口为 6032)。

    mysql -u admin -padmin -h 127.0.0.1 -P6032 --prompt 'ProxySQL Admin> '

    执行以上命令后,系统将显示 'ProxySQL Admin' 提示。

  2. 你可以在当前 MySQL 命令行客户端中向 ProxySQL 添加一个或多个 TiDB 集群。例如,下面的语句将添加一个 TiDB Dedicated 集群。你需要用集群的 EndpointPort 替换 <tidb cloud dedicated cluster host><tidb cloud dedicated cluster port>(默认端口为 4000)。

    INSERT INTO mysql_servers(hostgroup_id, hostname, port) VALUES ( 0, '<tidb cloud dedicated cluster host>', <tidb cloud dedicated cluster port> ); LOAD mysql servers TO runtime; SAVE mysql servers TO DISK;
  3. 为配置 ProxySQL 的登录用户,你需要确保用户在 TiDB 集群上有适当的权限。在下面的语句中,你需要把 <tidb cloud dedicated cluster username><tidb cloud dedicated cluster password> 替换为集群的实际用户名和密码。

    INSERT INTO mysql_users( username, password, active, default_hostgroup, transaction_persistent ) VALUES ( '<tidb cloud dedicated cluster username>', '<tidb cloud dedicated cluster password>', 1, 0, 1 ); LOAD mysql users TO runtime; SAVE mysql users TO DISK;
选项 2: 使用配置文件配置 ProxySQL

这个选项只能作为配置 ProxySQL 的备用方案。更多信息,可参考使用配置文件配置 ProxySQL

  1. 删除现有的 SQLite 数据库,即 ProxySQL 存储配置的位置。

    rm /var/lib/proxysql/proxysql.db
  2. 根据你的需要修改配置文件 /etc/proxysql.cnf。例如:

    mysql_servers: ( { address="<tidb cloud dedicated cluster host>" port=<tidb cloud dedicated cluster port> hostgroup=0 max_connections=2000 } ) mysql_users: ( { username = "<tidb cloud dedicated cluster username>" password = "<tidb cloud dedicated cluster password>" default_hostgroup = 0 max_connections = 1000 default_schema = "test" active = 1 transaction_persistent = 1 } )

    在上面的例子中:

    • addressport 用于指定你的 TiDB Cloud 集群的 EndpointPort
    • usernamepassword 用于指定你的 TiDB Cloud 集群的用户名和密码。
  3. 重启 ProxySQL:

    systemctl restart proxysql

    重新启动后,ProxySQL 将自动创建 SQLite 数据库。

典型场景

本节以查询规则为例,介绍集成 TiDB 与 ProxySQL 能带来的一些优势。

查询规则

数据库可能会因为高流量、错误代码或恶意攻击而过载。因此,审核 SQL 是必要的。使用 ProxySQL 的查询规则,你可以有效地应对这些问题,例如通过重路由、改写 SQL 或者拒绝查询等方式。

proxysql-client-side-rules

  1. 克隆 TiDB 和 ProxySQL 的集成示例代码仓库 pingcap-inc/tidb-proxysql-integration。如果你已经在前面的步骤中克隆了它,请跳过这一步。

    • macOS
    • CentOS
    • Windows (Git Bash)
    git clone https://github.com/pingcap-inc/tidb-proxysql-integration.git
    git clone https://github.com/pingcap-inc/tidb-proxysql-integration.git
    git clone https://github.com/pingcap-inc/tidb-proxysql-integration.git
  2. 进入 ProxySQL 查询规则的示例目录:

    • macOS
    • CentOS
    • Windows (Git Bash)
    cd tidb-proxysql-integration/example/proxy-rule-admin-interface
    cd tidb-proxysql-integration/example/proxy-rule-admin-interface
    cd tidb-proxysql-integration/example/proxy-rule-admin-interface
  3. 运行下面的命令启动两个 TiDB 容器和一个 ProxySQL 容器:

    • macOS
    • CentOS
    • Windows (Git Bash)
    docker compose up -d
    docker compose up -d
    docker compose up -d

    如果运行成功,以下容器将被启动:

    • 两个 Docker 容器的 TiDB 集群,端口分别为 40014002
    • 一个 Docker 容器的 ProxySQL,端口为 6034
  4. 在两个 TiDB 容器中,使用 mysql 创建一个具有相同 schema 的表,然后插入不同的数据 ('tidb-server01-port-4001', 'tidb-server02-port-4002') 以区分这两个容器。

    • macOS
    • CentOS
    • Windows (Git Bash)
    mysql -u root -h 127.0.0.1 -P 4001 << EOF DROP TABLE IF EXISTS test.tidb_server; CREATE TABLE test.tidb_server (server_name VARCHAR(255)); INSERT INTO test.tidb_server (server_name) VALUES ('tidb-server01-port-4001'); EOF mysql -u root -h 127.0.0.1 -P 4002 << EOF DROP TABLE IF EXISTS test.tidb_server; CREATE TABLE test.tidb_server (server_name VARCHAR(255)); INSERT INTO test.tidb_server (server_name) VALUES ('tidb-server02-port-4002'); EOF
    mysql -u root -h 127.0.0.1 -P 4001 << EOF DROP TABLE IF EXISTS test.tidb_server; CREATE TABLE test.tidb_server (server_name VARCHAR(255)); INSERT INTO test.tidb_server (server_name) VALUES ('tidb-server01-port-4001'); EOF mysql -u root -h 127.0.0.1 -P 4002 << EOF DROP TABLE IF EXISTS test.tidb_server; CREATE TABLE test.tidb_server (server_name VARCHAR(255)); INSERT INTO test.tidb_server (server_name) VALUES ('tidb-server02-port-4002'); EOF
    mysql -u root -h 127.0.0.1 -P 4001 << EOF DROP TABLE IF EXISTS test.tidb_server; CREATE TABLE test.tidb_server (server_name VARCHAR(255)); INSERT INTO test.tidb_server (server_name) VALUES ('tidb-server01-port-4001'); EOF mysql -u root -h 127.0.0.1 -P 4002 << EOF DROP TABLE IF EXISTS test.tidb_server; CREATE TABLE test.tidb_server (server_name VARCHAR(255)); INSERT INTO test.tidb_server (server_name) VALUES ('tidb-server02-port-4002'); EOF
  5. 运行下面的命令配置 ProxySQL,该命令会在 ProxySQL Admin Interface 中执行 proxysql-prepare.sql,从而在 TiDB 容器和 ProxySQL 之间建立一个代理连接。

    • macOS
    • CentOS
    • Windows (Git Bash)
    docker compose exec proxysql sh -c "mysql -uadmin -padmin -h127.0.0.1 -P6032 < ./proxysql-prepare.sql"
    docker compose exec proxysql sh -c "mysql -uadmin -padmin -h127.0.0.1 -P6032 < ./proxysql-prepare.sql"
    docker compose exec proxysql sh -c "mysql -uadmin -padmin -h127.0.0.1 -P6032 < ./proxysql-prepare.sql"

    下面是关于 ProxySQL 匹配 SQL 查询的规则的一些补充信息:

    • ProxySQL 尝试按照 rule_id 的升序逐一匹配规则。
    • 规则中的 ^ 符号用于匹配 SQL 语句的开头,$ 符号用于匹配语句的结尾。

    关于 ProxySQL 正则表达式和模式匹配的更多信息,参考 ProxySQL 文档 mysql-query_processor_regex

    关于完整的参数列表,参考 ProxySQL 文档 mysql_query_rules

  6. 验证配置并检查查询规则是否有效。

    1. 使用 root 用户登录 ProxySQL MySQL Interface:

      • macOS
      • CentOS
      • Windows (Git Bash)
      mysql -u root -h 127.0.0.1 -P 6034
      mysql -u root -h 127.0.0.1 -P 6034
      mysql -u root -h 127.0.0.1 -P 6034
    2. 执行以下 SQL 语句:

      • 执行一个 SELECT 语句:

        SELECT * FROM test.tidb_server;

        这个语句将匹配 rule_id2 的规则,因此将转发语句到 hostgroup1 上的 TiDB 集群中。

      • 执行一个 SELECT ... FOR UPDATE 语句:

        SELECT * FROM test.tidb_server FOR UPDATE;

        这个语句将匹配 rule_id1 的规则,因此将转发语句到 hostgroup0 上的 TiDB 集群中。

      • 启动一个事务:

        BEGIN; INSERT INTO test.tidb_server (server_name) VALUES ('insert this and rollback later'); SELECT * FROM test.tidb_server; ROLLBACK;

        在这个事务中,BEGIN 语句将不会匹配任何规则。因此,它将使用默认的 hostgroup(在这个例子中为 hostgroup 0)。因为 ProxySQL 默认启用了用户 transaction_persistent,它将在同一事务中,将所有语句都转发至相同的 hostgroup,所以 INSERTSELECT * FROM test.tidb_server; 语句也将被转发到 hostgroup0 的 TiDB 集群。

      下面是一个输出示例。如果你得到类似的输出,表示你已经成功配置了 ProxySQL 的查询规则。

      +-------------------------+ | server_name | +-------------------------+ | tidb-server02-port-4002 | +-------------------------+ +-------------------------+ | server_name | +-------------------------+ | tidb-server01-port-4001 | +-------------------------+ +--------------------------------+ | server_name | +--------------------------------+ | tidb-server01-port-4001 | | insert this and rollback later | +--------------------------------+
    3. 如需退出 MySQL 客户端,输入 quit 并按下 Enter 键。

  7. 要停止和删除容器,并返回上一个目录,运行以下命令:

    • macOS
    • CentOS
    • Windows (Git Bash)
    docker compose down cd -
    docker compose down cd -
    docker compose down cd -