Commit 607b2e33769a11f7b86a1766b6fbc0897e6fd819

Authored by YunaiV
1 parent 88bdc7a2

feat: 增加 TiDB 可选测试环境与初始化脚本

sql/tools/README.md
... ... @@ -6,7 +6,7 @@
6 6  
7 7 ## 1. 测试数据库的快速启动
8 8  
9   -基于 Docker Compose,快速启动 MySQL、Oracle、PostgreSQL、SQL Server、OceanBase 等数据库。
  9 +基于 Docker Compose,快速启动 MySQL、Oracle、PostgreSQL、SQL Server、OceanBase、TiDB 等数据库。
10 10  
11 11 注意!使用 Docker Compose 启动完测试数据后,因为会自动导入项目的 SQL 脚本,所以可能需要等待 1-2 分钟。
12 12  
... ... @@ -139,6 +139,34 @@ password: 123456
139 139  
140 140 > 注意:`root@test` 连接的是 MySQL 模式的 `test` 租户。配置了多个数据源时,需要同步修改对应配置。数据和部署配置分别保存在 `oceanbase`、`oceanbase_config` 数据卷中,重启不需要重新导入 SQL。镜像说明见 [OceanBase 官方文档](https://github.com/oceanbase/docker-images/blob/main/oceanbase-ce/README_CN.md)。
141 141  
  142 +### 1.10 TiDB
  143 +
  144 +使用 TiDB v8.5.8 官方镜像,启动 PD、TiKV、TiDB 各 1 个节点的测试集群,支持 x86_64 和 MacBook Apple Silicon。相关服务属于 `tidb` profile,执行 `docker compose up -d` 时不会启动。
  145 +
  146 +① 启动数据库,等待 TiDB 健康检查通过:
  147 +
  148 +```Bash
  149 +docker compose up -d --wait --wait-timeout 300 tidb
  150 +```
  151 +
  152 +② 初始化数据库:设置 `root` 密码为 `123456`,创建 `ruoyi-vue-pro` 数据库,并依次导入 `sql/mysql/ruoyi-vue-pro.sql`、`sql/mysql/quartz.sql`:
  153 +
  154 +```Bash
  155 +docker compose run --rm tidb-init
  156 +```
  157 +
  158 +> 注意:TiDB 直接复用 MySQL 脚本,不需要单独的 TiDB 脚本。初始化只允许创建全新的数据库:数据库已存在(包括空库)或重复执行时,脚本拒绝导入并返回非零状态,避免重建已有的同名表;导入失败时保留数据库便于排查,重新初始化需要删除数据卷。`TIDB_PASSWORD` 只允许字母、数字和 `_ . @ # % + = -` 字符。
  159 +
  160 +③ 项目继续使用 MySQL JDBC 驱动,将数据源配置中的地址、账号和密码修改为:
  161 +
  162 +```yaml
  163 +url: jdbc:mysql://127.0.0.1:4000/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true
  164 +username: root
  165 +password: 123456
  166 +```
  167 +
  168 +> 注意:端口只绑定本机 `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/)。
  169 +
142 170 ## 1.X 容器的销毁重建
143 171  
144 172 开发测试过程中,有时候需要创建全新干净的数据库。由于测试数据 Docker 容器采用数据卷 Volume 挂载数据库实例的数据目录,因此销毁数据需要停止容器后,删除数据卷,然后再重新创建容器。
... ...
sql/tools/docker-compose.yaml
... ... @@ -10,6 +10,8 @@ volumes:
10 10 highgo: { }
11 11 oceanbase: { }
12 12 oceanbase_config: { }
  13 + tidb_pd: { }
  14 + tidb_tikv: { }
13 15  
14 16 services:
15 17 mysql:
... ... @@ -173,3 +175,79 @@ services:
173 175 timeout: 5s
174 176 start_period: 120s
175 177 retries: 30
  178 +
  179 + # TiDB 测试集群:PD、TiKV、TiDB 各 1 个节点,属于 tidb profile,默认不启动
  180 + # 启动:docker compose up -d --wait --wait-timeout 300 tidb
  181 + tidb-pd:
  182 + image: pingcap/pd:v8.5.8
  183 + profiles: ["tidb"]
  184 + restart: unless-stopped
  185 + command:
  186 + - --name=pd
  187 + - --client-urls=http://0.0.0.0:2379
  188 + - --peer-urls=http://0.0.0.0:2380
  189 + - --advertise-client-urls=http://tidb-pd:2379
  190 + - --advertise-peer-urls=http://tidb-pd:2380
  191 + - --initial-cluster=pd=http://tidb-pd:2380
  192 + - --data-dir=/data/pd
  193 + - --config=/pd.toml
  194 + volumes:
  195 + - tidb_pd:/data
  196 + - ./tidb/pd.toml:/pd.toml:ro
  197 +
  198 + tidb-tikv:
  199 + image: pingcap/tikv:v8.5.8
  200 + profiles: ["tidb"]
  201 + restart: unless-stopped
  202 + command:
  203 + - --addr=0.0.0.0:20160
  204 + - --advertise-addr=tidb-tikv:20160
  205 + - --status-addr=0.0.0.0:20180
  206 + - --advertise-status-addr=tidb-tikv:20180
  207 + - --data-dir=/data/tikv
  208 + - --pd=tidb-pd:2379
  209 + - --config=/tikv.toml
  210 + volumes:
  211 + - tidb_tikv:/data
  212 + - ./tidb/tikv.toml:/tikv.toml:ro
  213 + depends_on:
  214 + - tidb-pd
  215 +
  216 + tidb:
  217 + image: pingcap/tidb:v8.5.8
  218 + profiles: ["tidb"]
  219 + restart: unless-stopped
  220 + environment:
  221 + TZ: Asia/Shanghai
  222 + command:
  223 + - --store=tikv
  224 + - --path=tidb-pd:2379
  225 + - --advertise-address=tidb
  226 + ports:
  227 + # 只绑定本机,root 密码由 tidb-init 初始化
  228 + - "127.0.0.1:4000:4000"
  229 + depends_on:
  230 + - tidb-tikv
  231 + healthcheck:
  232 + test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:10080/status >/dev/null"]
  233 + interval: 10s
  234 + timeout: 5s
  235 + start_period: 60s
  236 + retries: 30
  237 +
  238 + # TiDB 初始化:设置 root 密码,创建 ruoyi-vue-pro 数据库并导入 MySQL 脚本,只允许创建全新数据库
  239 + # 执行:docker compose run --rm tidb-init
  240 + tidb-init:
  241 + image: mysql:8.0.33
  242 + profiles: ["tidb-init"]
  243 + restart: "no"
  244 + environment:
  245 + TIDB_HOST: tidb
  246 + TIDB_PORT: 4000
  247 + TIDB_DATABASE: ruoyi-vue-pro
  248 + TIDB_PASSWORD: "123456"
  249 + entrypoint: ["bash", "/tmp/create_schema.sh"]
  250 + volumes:
  251 + - ../mysql/ruoyi-vue-pro.sql:/tmp/schema.sql:ro
  252 + - ../mysql/quartz.sql:/tmp/quartz.sql:ro
  253 + - ./tidb/create_schema.sh:/tmp/create_schema.sh:ro
... ...
sql/tools/tidb/create_schema.sh 0 → 100644
  1 +#!/bin/bash
  2 +# 初始化 TiDB 测试库:只允许创建全新的数据库并导入项目 SQL,数据库已存在(包括空库)时拒绝导入;任一步骤失败都以非零状态退出
  3 +set -euo pipefail
  4 +
  5 +host="${TIDB_HOST:-tidb}"
  6 +port="${TIDB_PORT:-4000}"
  7 +database="${TIDB_DATABASE:-ruoyi-vue-pro}"
  8 +password="${TIDB_PASSWORD:?TIDB_PASSWORD 未设置}"
  9 +
  10 +if [[ ! "${database}" =~ ^[A-Za-z0-9_-]+$ ]]; then
  11 + echo "数据库名 ${database} 不合法,只允许字母、数字、下划线和中划线" >&2
  12 + exit 1
  13 +fi
  14 +# 密码会拼接到 ALTER USER 语句中,只允许不需要转义的字符
  15 +if [[ ! "${password}" =~ ^[A-Za-z0-9_.@#%+=-]+$ ]]; then
  16 + echo "TIDB_PASSWORD 不合法,只允许字母、数字和 _ . @ # % + = - 字符" >&2
  17 + exit 1
  18 +fi
  19 +
  20 +client=(mysql -h"${host}" -P"${port}" -uroot --default-character-set=utf8mb4)
  21 +
  22 +# 1. 等待 TiDB 可连接(首次启动时 PD、TiKV 需要一段时间完成初始化)
  23 +for i in $(seq 1 60); do
  24 + if mysqladmin -h"${host}" -P"${port}" -uroot --connect-timeout=3 ping >/dev/null 2>&1; then
  25 + break
  26 + fi
  27 + if [ "${i}" -eq 60 ]; then
  28 + echo "等待 TiDB ${host}:${port} 超时,请执行 docker compose logs tidb 检查启动日志" >&2
  29 + exit 1
  30 + fi
  31 + sleep 5
  32 +done
  33 +
  34 +# 2. 新集群的 root 默认没有密码,首次初始化时设置为 TIDB_PASSWORD
  35 +export MYSQL_PWD="${password}"
  36 +if ! "${client[@]}" -e 'SELECT 1' >/dev/null 2>&1; then
  37 + env -u MYSQL_PWD "${client[@]}" -e "ALTER USER 'root'@'%' IDENTIFIED BY '${password}';"
  38 +fi
  39 +
  40 +# 3. 创建全新数据库:不使用 IF NOT EXISTS,数据库已存在时直接失败,避免项目 SQL 中的 DROP TABLE 重建已有的同名表
  41 +if ! "${client[@]}" -e "CREATE DATABASE \`${database}\` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"; then
  42 + echo "创建数据库 ${database} 失败:只允许初始化全新的数据库,数据库已存在(包括空库)时拒绝导入;如需重新初始化,请删除 TiDB 数据卷后重建" >&2
  43 + exit 1
  44 +fi
  45 +
  46 +# 4. 按 ruoyi-vue-pro、quartz 的顺序导入 MySQL 脚本(mysql 客户端遇到错误会立即退出,失败时保留数据库,便于排查)
  47 +"${client[@]}" -D "${database}" < /tmp/schema.sql
  48 +"${client[@]}" -D "${database}" < /tmp/quartz.sql
  49 +
  50 +table_count=$("${client[@]}" -N -B -e "SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = '${database}';")
  51 +echo "TiDB 初始化完成:数据库 ${database} 共 ${table_count} 张表"
... ...
sql/tools/tidb/pd.toml 0 → 100644
  1 +# 单机测试环境只有 1 个 TiKV,副本数设置为 1(仅在集群首次启动时生效)
  2 +[replication]
  3 +max-replicas = 1
... ...
sql/tools/tidb/tikv.toml 0 → 100644
  1 +# 测试环境限制 TiKV 块缓存,避免默认按宿主内存比例占用过多内存
  2 +[storage.block-cache]
  3 +capacity = "1GB"
... ...