博客 / 詳情

返回

玩一玩 proxysql

作者:張富春(ahfuzhang),轉載時請註明作者和引用鏈接,謝謝!

  • cnblogs博客
  • zhihu
  • Github
  • 公眾號:一本正經的瞎扯

一個後端服務的性能不好,我懷疑是數據庫拖慢了性能,為了便於不侵入代碼而對性能進行分析,我嘗試了 proxysql 組件:

在 mysql 客户端和 mysql 服務器之間搭建 proxysql 代理服務,通過 proxy 來記錄日誌、分析性能、做緩存

如下是使用過程:

部署

配置文件

如下是配置文件的格式: proxysql.cnf

datadir="/var/lib/proxysql"
errorlog="/log/proxysql.log"
admin_variables=
{
  admin_credentials="admin:admin"  # 管理員賬號
  mysql_ifaces="0.0.0.0:6032"  # mysql 協議管理端口
}

mysql_variables=
{
  threads=4
  max_connections=2048
  interfaces="0.0.0.0:6033"  # 代理端口
  default_schema="information_schema"
  monitor_username="monitor"
  monitor_password="monitor"
  #
  mysql-eventslog_filename="/log/events.log"
  mysql-eventslog_format=2          # JSON(可選)
  mysql-eventslog_default_log=1     # 全量記錄(可選)
}

# 先留空:你後面可用管理端口 6032 動態寫入後端/用户/規則
mysql_servers =
(
)

mysql_users =
(
)

啓動服務

docker run -d --rm --name proxysql \
	    --network host \
	    --cpus=1 -m=1024m \
		-p 6032:6032 -p 6033:6033 \
		-v "./proxysql.cnf:/etc/proxysql.cnf:ro" \
		-v "./data:/var/lib/proxysql" \
		-v "./log/":/log/ \
		proxysql/proxysql:latest

配置規則

使用寫入 sql 的方式來配置: config.sh

#!/usr/bin/env bash
set -euo pipefail

# ===== ProxySQL 管理端連接信息 =====
PROXYSQL_HOST="${PROXYSQL_HOST:-127.0.0.1}"
PROXYSQL_PORT="${PROXYSQL_PORT:-6032}"
PROXYSQL_ADMIN_USER="${PROXYSQL_ADMIN_USER:-admin}"
PROXYSQL_ADMIN_PASS="${PROXYSQL_ADMIN_PASS:-admin}"

# ===== 你要創建/更新的業務用户 =====
APP_USER="${APP_USER:-app}"
APP_PASS="${APP_PASS:-app_pw}"
DEFAULT_HOSTGROUP="${DEFAULT_HOSTGROUP:-10}"

mysql -h "${PROXYSQL_HOST}" -P "${PROXYSQL_PORT}" \
  -u "${PROXYSQL_ADMIN_USER}" -p"${PROXYSQL_ADMIN_PASS}" \
  --protocol=tcp --batch --raw --silent <<SQL

-- 1) 指定日誌文件名(相對 datadir;也可以給絕對路徑)
SET mysql-eventslog_filename='/log/events.log';

-- 2) JSON 格式(更好進 ELK/Loki)
SET mysql-eventslog_format=2;

-- 3) 默認記錄所有查詢
SET mysql-eventslog_default_log=1;

SET mysql-query_cache_size_MB = 512;


LOAD MYSQL VARIABLES TO RUNTIME;
SAVE MYSQL VARIABLES TO DISK;


INSERT INTO mysql_servers(hostgroup_id, hostname, port, weight, max_connections)
VALUES (10, 'myserver.com', 3306, 100, 20);
INSERT INTO mysql_users(username, password, default_hostgroup, active)
VALUES ('my_user_name', 'password', 10, 1);


LOAD MYSQL USERS TO RUNTIME;
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
SAVE MYSQL USERS TO DISK;

-- 規則儘量靠前(rule_id 小)
INSERT INTO mysql_query_rules
  (rule_id, active, match_pattern, re_modifiers, cache_ttl, apply)
VALUES
  (100, 1, '^SELECT\\s', 'CASELESS', 1000000, 1);  -- 所有的 select 查詢,對結果緩存 1000000 毫秒

LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;

-- 可選:打印確認
SELECT username, default_hostgroup, active
FROM mysql_users;

SQL

執行配置:

bash config.sh

客户端

客户端的 sql 服務器配置,把 host 修改為 proxysql 的 ip。例子中是 127.0.0.1
端口修改為 proxysql 的端口, 例子中是 6033.

開啓客户端運行後,在 proxysql 對應的 ./log/events.log.00000001 中,可以看到如下樣式的日誌:

{
    "client":"127.0.0.1:49606",
    "digest":"0x5F0C91291BB515C4",
    "duration_us":13992,
    "endtime":"2026-02-04 07:18:50.359984",
    "endtime_timestamp_us":1770189530359984,
    "errno":0,
    "event":"COM_QUERY",
    "hostgroup_id":10,
    "query":"SELECT * FROM `table1`\nWHERE `player_id` = 1234\n ORDER BY `update_time` DESC\n                    LIMIT 1",
    "rows_affected":0,
    "rows_sent":1,
    "schemaname":"my_db",
    "server":"server.com:3306",
    "starttime":"2026-02-04 07:18:50.345992",
    "starttime_timestamp_us":1770189530345992,
    "thread_id":4,
    "username":"my_user_name"
}
  • duration_us 字段記錄了 sql 的執行時間
  • query 字段可以看見具體的 sql

總結

這個組件至少能夠在測試階段做很多事情:

  • 把日誌接入到日誌分析系統,可以對慢查詢等進行統計
  • 便於做全局的 sql 治理的工作
  • 通過 sql 查詢結果緩存,提前評估數據緩存的收益
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.