From 607b2e33769a11f7b86a1766b6fbc0897e6fd819 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 25 Oct 2026 10:16:01 +0800 Subject: [PATCH] feat: 增加 TiDB 可选测试环境与初始化脚本 --- sql/tools/README.md | 30 +++++++++++++++++++++++++++++- sql/tools/docker-compose.yaml | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ sql/tools/tidb/create_schema.sh | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ sql/tools/tidb/pd.toml | 3 +++ sql/tools/tidb/tikv.toml | 3 +++ 5 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 sql/tools/tidb/create_schema.sh create mode 100644 sql/tools/tidb/pd.toml create mode 100644 sql/tools/tidb/tikv.toml diff --git a/sql/tools/README.md b/sql/tools/README.md index 4a16c7d..b2eb325 100644 --- a/sql/tools/README.md +++ b/sql/tools/README.md @@ -6,7 +6,7 @@ ## 1. 测试数据库的快速启动 -基于 Docker Compose,快速启动 MySQL、Oracle、PostgreSQL、SQL Server、OceanBase 等数据库。 +基于 Docker Compose,快速启动 MySQL、Oracle、PostgreSQL、SQL Server、OceanBase、TiDB 等数据库。 注意!使用 Docker Compose 启动完测试数据后,因为会自动导入项目的 SQL 脚本,所以可能需要等待 1-2 分钟。 @@ -139,6 +139,34 @@ password: 123456 > 注意:`root@test` 连接的是 MySQL 模式的 `test` 租户。配置了多个数据源时,需要同步修改对应配置。数据和部署配置分别保存在 `oceanbase`、`oceanbase_config` 数据卷中,重启不需要重新导入 SQL。镜像说明见 [OceanBase 官方文档](https://github.com/oceanbase/docker-images/blob/main/oceanbase-ce/README_CN.md)。 +### 1.10 TiDB + +使用 TiDB v8.5.8 官方镜像,启动 PD、TiKV、TiDB 各 1 个节点的测试集群,支持 x86_64 和 MacBook Apple Silicon。相关服务属于 `tidb` profile,执行 `docker compose up -d` 时不会启动。 + +① 启动数据库,等待 TiDB 健康检查通过: + +```Bash +docker compose up -d --wait --wait-timeout 300 tidb +``` + +② 初始化数据库:设置 `root` 密码为 `123456`,创建 `ruoyi-vue-pro` 数据库,并依次导入 `sql/mysql/ruoyi-vue-pro.sql`、`sql/mysql/quartz.sql`: + +```Bash +docker compose run --rm tidb-init +``` + +> 注意:TiDB 直接复用 MySQL 脚本,不需要单独的 TiDB 脚本。初始化只允许创建全新的数据库:数据库已存在(包括空库)或重复执行时,脚本拒绝导入并返回非零状态,避免重建已有的同名表;导入失败时保留数据库便于排查,重新初始化需要删除数据卷。`TIDB_PASSWORD` 只允许字母、数字和 `_ . @ # % + = -` 字符。 + +③ 项目继续使用 MySQL JDBC 驱动,将数据源配置中的地址、账号和密码修改为: + +```yaml +url: jdbc:mysql://127.0.0.1:4000/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true +username: root +password: 123456 +``` + +> 注意:端口只绑定本机 `127.0.0.1:4000`。数据保存在 `tidb_pd`、`tidb_tikv` 数据卷中,重启不需要重新导入 SQL。如需重建,执行 `docker compose down tidb tidb-tikv tidb-pd` 后,删除 `ruoyi-vue-pro_tidb_pd`、`ruoyi-vue-pro_tidb_tikv` 数据卷。该环境仅用于开发测试,生产部署见 [TiDB 官方文档](https://docs.pingcap.com/zh/tidb/v8.5/production-deployment-using-tiup/)。 + ## 1.X 容器的销毁重建 开发测试过程中,有时候需要创建全新干净的数据库。由于测试数据 Docker 容器采用数据卷 Volume 挂载数据库实例的数据目录,因此销毁数据需要停止容器后,删除数据卷,然后再重新创建容器。 diff --git a/sql/tools/docker-compose.yaml b/sql/tools/docker-compose.yaml index bcbe175..bb8bf46 100644 --- a/sql/tools/docker-compose.yaml +++ b/sql/tools/docker-compose.yaml @@ -10,6 +10,8 @@ volumes: highgo: { } oceanbase: { } oceanbase_config: { } + tidb_pd: { } + tidb_tikv: { } services: mysql: @@ -173,3 +175,79 @@ services: timeout: 5s start_period: 120s retries: 30 + + # TiDB 测试集群:PD、TiKV、TiDB 各 1 个节点,属于 tidb profile,默认不启动 + # 启动:docker compose up -d --wait --wait-timeout 300 tidb + tidb-pd: + image: pingcap/pd:v8.5.8 + profiles: ["tidb"] + restart: unless-stopped + command: + - --name=pd + - --client-urls=http://0.0.0.0:2379 + - --peer-urls=http://0.0.0.0:2380 + - --advertise-client-urls=http://tidb-pd:2379 + - --advertise-peer-urls=http://tidb-pd:2380 + - --initial-cluster=pd=http://tidb-pd:2380 + - --data-dir=/data/pd + - --config=/pd.toml + volumes: + - tidb_pd:/data + - ./tidb/pd.toml:/pd.toml:ro + + tidb-tikv: + image: pingcap/tikv:v8.5.8 + profiles: ["tidb"] + restart: unless-stopped + command: + - --addr=0.0.0.0:20160 + - --advertise-addr=tidb-tikv:20160 + - --status-addr=0.0.0.0:20180 + - --advertise-status-addr=tidb-tikv:20180 + - --data-dir=/data/tikv + - --pd=tidb-pd:2379 + - --config=/tikv.toml + volumes: + - tidb_tikv:/data + - ./tidb/tikv.toml:/tikv.toml:ro + depends_on: + - tidb-pd + + tidb: + image: pingcap/tidb:v8.5.8 + profiles: ["tidb"] + restart: unless-stopped + environment: + TZ: Asia/Shanghai + command: + - --store=tikv + - --path=tidb-pd:2379 + - --advertise-address=tidb + ports: + # 只绑定本机,root 密码由 tidb-init 初始化 + - "127.0.0.1:4000:4000" + depends_on: + - tidb-tikv + healthcheck: + test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:10080/status >/dev/null"] + interval: 10s + timeout: 5s + start_period: 60s + retries: 30 + + # TiDB 初始化:设置 root 密码,创建 ruoyi-vue-pro 数据库并导入 MySQL 脚本,只允许创建全新数据库 + # 执行:docker compose run --rm tidb-init + tidb-init: + image: mysql:8.0.33 + profiles: ["tidb-init"] + restart: "no" + environment: + TIDB_HOST: tidb + TIDB_PORT: 4000 + TIDB_DATABASE: ruoyi-vue-pro + TIDB_PASSWORD: "123456" + entrypoint: ["bash", "/tmp/create_schema.sh"] + volumes: + - ../mysql/ruoyi-vue-pro.sql:/tmp/schema.sql:ro + - ../mysql/quartz.sql:/tmp/quartz.sql:ro + - ./tidb/create_schema.sh:/tmp/create_schema.sh:ro diff --git a/sql/tools/tidb/create_schema.sh b/sql/tools/tidb/create_schema.sh new file mode 100644 index 0000000..dd381be --- /dev/null +++ b/sql/tools/tidb/create_schema.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# 初始化 TiDB 测试库:只允许创建全新的数据库并导入项目 SQL,数据库已存在(包括空库)时拒绝导入;任一步骤失败都以非零状态退出 +set -euo pipefail + +host="${TIDB_HOST:-tidb}" +port="${TIDB_PORT:-4000}" +database="${TIDB_DATABASE:-ruoyi-vue-pro}" +password="${TIDB_PASSWORD:?TIDB_PASSWORD 未设置}" + +if [[ ! "${database}" =~ ^[A-Za-z0-9_-]+$ ]]; then + echo "数据库名 ${database} 不合法,只允许字母、数字、下划线和中划线" >&2 + exit 1 +fi +# 密码会拼接到 ALTER USER 语句中,只允许不需要转义的字符 +if [[ ! "${password}" =~ ^[A-Za-z0-9_.@#%+=-]+$ ]]; then + echo "TIDB_PASSWORD 不合法,只允许字母、数字和 _ . @ # % + = - 字符" >&2 + exit 1 +fi + +client=(mysql -h"${host}" -P"${port}" -uroot --default-character-set=utf8mb4) + +# 1. 等待 TiDB 可连接(首次启动时 PD、TiKV 需要一段时间完成初始化) +for i in $(seq 1 60); do + if mysqladmin -h"${host}" -P"${port}" -uroot --connect-timeout=3 ping >/dev/null 2>&1; then + break + fi + if [ "${i}" -eq 60 ]; then + echo "等待 TiDB ${host}:${port} 超时,请执行 docker compose logs tidb 检查启动日志" >&2 + exit 1 + fi + sleep 5 +done + +# 2. 新集群的 root 默认没有密码,首次初始化时设置为 TIDB_PASSWORD +export MYSQL_PWD="${password}" +if ! "${client[@]}" -e 'SELECT 1' >/dev/null 2>&1; then + env -u MYSQL_PWD "${client[@]}" -e "ALTER USER 'root'@'%' IDENTIFIED BY '${password}';" +fi + +# 3. 创建全新数据库:不使用 IF NOT EXISTS,数据库已存在时直接失败,避免项目 SQL 中的 DROP TABLE 重建已有的同名表 +if ! "${client[@]}" -e "CREATE DATABASE \`${database}\` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"; then + echo "创建数据库 ${database} 失败:只允许初始化全新的数据库,数据库已存在(包括空库)时拒绝导入;如需重新初始化,请删除 TiDB 数据卷后重建" >&2 + exit 1 +fi + +# 4. 按 ruoyi-vue-pro、quartz 的顺序导入 MySQL 脚本(mysql 客户端遇到错误会立即退出,失败时保留数据库,便于排查) +"${client[@]}" -D "${database}" < /tmp/schema.sql +"${client[@]}" -D "${database}" < /tmp/quartz.sql + +table_count=$("${client[@]}" -N -B -e "SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = '${database}';") +echo "TiDB 初始化完成:数据库 ${database} 共 ${table_count} 张表" diff --git a/sql/tools/tidb/pd.toml b/sql/tools/tidb/pd.toml new file mode 100644 index 0000000..41d1001 --- /dev/null +++ b/sql/tools/tidb/pd.toml @@ -0,0 +1,3 @@ +# 单机测试环境只有 1 个 TiKV,副本数设置为 1(仅在集群首次启动时生效) +[replication] +max-replicas = 1 diff --git a/sql/tools/tidb/tikv.toml b/sql/tools/tidb/tikv.toml new file mode 100644 index 0000000..ee99fad --- /dev/null +++ b/sql/tools/tidb/tikv.toml @@ -0,0 +1,3 @@ +# 测试环境限制 TiKV 块缓存,避免默认按宿主内存比例占用过多内存 +[storage.block-cache] +capacity = "1GB" -- libgit2 0.21.4