用户登录
个人主页 用户中心 我的订单 添加授权 管理授权
退出登录
用户登录 用户注册
欢迎来到 UC建站系统

30个站批量改一个字段是逐站连Navicat手动改还是写条命令3秒跑完,数据库批量执行四种方案效率从低到高

30个站批量改一个字段,你是一个个连Navicat手动改,还是写条命令3秒跑完?数据库批量执行的四种方案,效率从低到高

有个站长在群里吐槽:新上线了40个站,每个站都要跑一套初始化SQL脚本,建表、插入默认数据、创建索引,加起来每个站大概30个SQL文件。他花了整整两天,一个个连Navicat,选数据库,右键"运行SQL文件",等进度条跑完,再切下一个库。改到第23个的时候Navicat崩了,前面的操作还没记哪些站跑过哪些没跑,只能从头来。

这其实是一个很典型的多库批量操作场景。站群、SaaS多租户、微服务分库,只要管理的数据库超过5个,手动连客户端一个一个点就是纯粹的体力活。更危险的是人工操作容易出错——漏执行、重复执行、执行顺序搞错,每一样都可能导致线上数据不一致。这篇文章把数据库批量执行的方案从最基础到最自动化排一遍,每个方案的适用场景、优缺点和实际脚本都摆出来。

数据库批量执行 四种方案速览

1GUI工具批量功能 — Navicat批处理作业、DBeaver任务调度,适合偶尔操作、不想写代码的场景
2Shell脚本循环执行 — 一个for循环搞定多库,灵活度最高,Linux服务器上标配方案
3数据库迁移工具 — Flyway / Liquibase,带版本管理,适合开发环境和持续部署
4并发批量框架 — DataX / DBSyncer / 自定义Go脚本,数据量大、时效要求高的场景

一、GUI工具的批量执行功能,最多人用但最容易被误用

Navicat和DBeaver都内置了批量执行能力,但很多人不知道或者用错了。先说Navicat。

Navicat的"批处理作业"藏在"自动运行"菜单里。你可以创建一个批处理,把多个"运行SQL文件"任务拖进去,设置好每个任务对应的数据库连接。然后点"运行",Navicat会按顺序逐个执行。关键点是:默认情况下,Navicat的批处理作业遇到一个SQL报错就会停下来,后面的任务不再执行。所以如果你跑的是初始化脚本,一定要勾选"忽略SQL语句错误"选项,否则中间某个文件有个小语法问题,整个批处理就卡住了。

Navicat批处理的一个坑:它不支持自动选择多个.sql文件拖入。如果你把10个.sql文件拖到批处理窗口,只会导入第一个。正确做法是逐个添加"运行SQL文件"任务,或者用命令行把多个.sql文件合并成一个再导入。另外,Navicat的批处理只能手动触发,没有定时调度能力,不能设置"每天凌晨3点自动跑"。

DBeaver的"任务调度"功能比Navicat强一档。在DBeaver里,你可以创建一个Task,配置多个SQL脚本的执行顺序,并设置每个脚本对应的数据库连接。而且DBeaver支持导出任务配置为XML文件,可以复用。但DBeaver也有短板——它跨数据库执行的时候不支持并发,还是串行的。

1 - 30个站批量改一个字段是逐站连Navicat手动改还是写条命令3秒跑完,数据库批量执行四种方案效率从低到高 - UC建站系统

什么时候用GUI批量就够了?

数据库不超过10个,偶尔执行一次批量操作(比如月初更新配置表),不想折腾命令行——这种情况GUI批量完全够用。但如果数据库超过20个,或者需要定时执行、需要在多台服务器上执行,就该往下看了。

二、Shell脚本循环执行,20行代码解决90%的批量场景

这是最灵活的方案,也是生产环境里用得最多的。核心思路:一个for循环遍历数据库列表,对每个库执行mysql命令,记录日志,遇到错误可以选择跳过或中断。下面是几个实用的脚本模板。

基础版:单SQL文件跑多个数据库

#!/bin/bash# 在所有站点数据库中执行同一个SQL文件MYSQL_USER="root"MYSQL_PASS="your_password"MYSQL_HOST="127.0.0.1"SQL_FILE="/home/sql/update_config.sql"LOG_FILE="/home/sql/batch_exec_$(date +%Y%m%d_%H%M%S).log"# 数据库列表,格式:每行一个库名DATABASES=("site_001_db""site_002_db""site_003_db"# ... 继续添加)SUCCESS=0FAIL=0for db in "${DATABASES[@]}"; doecho "[$(date '+%H:%M:%S')] 正在执行: $db ..." | tee -a "$LOG_FILE"mysql -u"$MYSQL_USER" -p"$MYSQL_PASS" -h"$MYSQL_HOST" "$db" < "$SQL_FILE" 2>> "$LOG_FILE"if [ $? -eq 0 ]; thenecho "  ✓ $db 执行成功" | tee -a "$LOG_FILE"((SUCCESS++))elseecho "  ✗ $db 执行失败,请检查日志" | tee -a "$LOG_FILE"((FAIL++))fidoneecho "==============================" | tee -a "$LOG_FILE"echo "执行完成:成功 $SUCCESS 个,失败 $FAIL 个" | tee -a "$LOG_FILE"

进阶版:多SQL文件按顺序跑 + 并发控制

#!/bin/bash# 多个SQL文件按顺序执行,支持并发(同时跑N个库)MYSQL_USER="root"MYSQL_PASS="your_password"MYSQL_HOST="127.0.0.1"SQL_DIR="/home/sql/init_scripts"      # SQL文件目录MAX_PARALLEL=5                         # 最大并发数# SQL文件列表(按执行顺序排列)SQL_FILES=("01_create_tables.sql""02_add_indexes.sql""03_insert_defaults.sql""04_create_views.sql")DATABASES=($(mysql -u"$MYSQL_USER" -p"$MYSQL_PASS" -h"$MYSQL_HOST" -e "SHOW DATABASES LIKE 'site_%';" -sN))exec_sql_for_db() {local db=$1local log="/tmp/batch_${db}.log"echo "[$(date '+%H:%M:%S')] 开始执行 $db" > "$log"for sql_file in "${SQL_FILES[@]}"; domysql -u"$MYSQL_USER" -p"$MYSQL_PASS" -h"$MYSQL_HOST" "$db" < "$SQL_DIR/$sql_file" 2>> "$log"if [ $? -ne 0 ]; thenecho "  ✗ $sql_file 失败" >> "$log"return 1fidoneecho "  ✓ $db 全部完成" >> "$log"}# 并发控制:后台执行,用wait控制并发数running=0for db in "${DATABASES[@]}"; doexec_sql_for_db "$db" &((running++))if [ $running -ge $MAX_PARALLEL ]; thenwait -n   # 等任意一个完成((running--))fidonewait  # 等所有后台任务完成echo "所有数据库执行完毕"

Shell脚本批量执行的三个坑

1. 密码明文问题:不要在脚本里直接写密码。用 mysql_config_editor 设置免密登录,或者把密码放在 ~/.my.cnf 里设600权限。
2. 超时断开:大SQL文件执行时间长了mysql连接会断开。在执行前先设 SET SESSION wait_timeout=86400;
3. 并发不要太高:同时跑太多库会打满数据库连接数和磁盘IO。一般建议并发数不超过CPU核数的2倍,单个SQL文件超过100MB就不要并发了。

三、Flyway和Liquibase,不只是批量执行,更是一套版本管理体系

如果批量执行SQL是你的日常操作——比如每天都有表结构变更、每周都有新站初始化——那Shell脚本会逐渐暴露出一个问题:没有版本追踪。你不知道每个库当前跑到了哪个版本的SQL,不知道哪些库漏执行了某个脚本,回滚也基本靠手工。

Flyway和Liquibase就是解决这个问题的。它们都是数据库迁移(Migration)工具,核心思路是:把每次数据库变更记录为一个版本,工具自动追踪每个库当前版本,只执行还没跑过的脚本。

对比维度FlywayLiquibase
脚本格式纯SQL文件(V1__xxx.sql)XML / YAML / JSON / SQL 都支持
版本追踪表自动创建 flyway_schema_history自动创建 DATABASECHANGELOG
回滚支持社区版不支持,企业版支持原生支持rollback
学习成本低,会写SQL就会用中等,需要学ChangeSet语法
多数据库支持25+ 种数据库30+ 种数据库
站群场景适配用命令行 + Shell循环包装用contexts区分不同站点的变更

站群场景下Flyway怎么用:每个站点一个独立数据库,用Shell脚本在外面包一层循环,对每个库执行flyway migrate命令。Flyway会自动检查该库的flyway_schema_history表,只跑没执行过的版本。这样你不需要记住"这个库跑到了V3还是V5",Flyway帮你记。

Flyway + Shell 批量迁移示例

#!/bin/bashFLYWAY_HOME="/opt/flyway"for db in site_001 site_002 site_003; do$FLYWAY_HOME/flyway \-url="jdbc:mysql://localhost:3306/${db}_db" \-user=root -password=xxx \-locations="filesystem:/home/sql/migrations" \migratedone

Liquibase更适合复杂场景。如果你的站群不是每个站结构完全一样——比如A类站点多几个表、B类站点少几个字段——Liquibase的contexts和labels机制可以按标签区分哪些变更应用到哪些库,比Flyway更灵活。但代价是学习成本高,ChangeSet的XML写起来比纯SQL繁琐。

2 - 30个站批量改一个字段是逐站连Navicat手动改还是写条命令3秒跑完,数据库批量执行四种方案效率从低到高 - UC建站系统

四、并发批量框架,当数据量和时效都上来的时候

Shell脚本的for循环并发有个天花板:它是进程级的并发,每个mysql命令fork一个进程,进程数多了开销很大。如果你有上百个库需要同时执行,或者单个SQL文件几百MB,Shell脚本就开始力不从心了。这时候要用专门的批量执行框架。

DataX(阿里开源)

专为数据同步设计的框架,支持MySQL、Oracle、PostgreSQL等十几种数据源之间的批量读写。优势是支持多Channel并发,一个大表可以切成N个分片同时读写,速度比单线程快5-10倍。适合数据迁移、多库同步场景。

DBSyncer(开源中间件)

实时数据同步中间件,支持全量+增量同步。特点是自带监控面板,能看到每个同步任务的实时速率、延迟、错误数。还支持自定义插件做数据转换。适合需要持续同步而不是一次性执行的场景。

自写Go脚本

如果你对性能有极致要求,用Go写一个批量执行器是最优解。goroutine天然适合并发,一个goroutine对应一个数据库连接,几百个库同时跑毫无压力。加上连接池管理和错误重试逻辑,50行代码就能写出比Shell强一个数量级的批量工具。

这里给一个Go语言批量执行的极简示例,30个数据库同时跑,每个库一个goroutine:

package mainimport ("database/sql""fmt""sync"_ "github.com/go-sql-driver/mysql")func main() {dbs := []string{"site_001", "site_002", /* ... site_030 */}sqlContent, _ := os.ReadFile("/home/sql/update.sql")var wg sync.WaitGroupsem := make(chan struct{}, 10) // 最多10个并发连接for _, db := range dbs {wg.Add(1)go func(dbName string) {defer wg.Done()sem <- struct{}{}        // 获取信号量defer func() { <-sem }() // 释放信号量dsn := fmt.Sprintf("root:pass@tcp(127.0.0.1:3306)/%s", dbName)conn, _ := sql.Open("mysql", dsn)defer conn.Close()_, err := conn.Exec(string(sqlContent))if err != nil {fmt.Printf("✗ %s: %v\n", dbName, err)return}fmt.Printf("✓ %s 执行成功\n", dbName)}(db + "_db")}wg.Wait()fmt.Println("全部执行完毕")}

五、四种方案怎么选,一张图说清楚

你的情况推荐方案理由
不到10个库,一个月操作一两次Navicat / DBeaver 批处理不折腾,点几下鼠标就完事
10-50个库,每周都有批量操作Shell脚本 + for循环灵活、免费、几乎所有Linux都自带
需要版本管理,多人协作开发Flyway / Liquibase自动追踪版本,不会重复执行或遗漏
50+个库,数据量大,时效要求高Go脚本 / DataX / DBSyncer并发能力、错误处理、监控都比Shell强
站群,每个站独立库,经常批量改Shell脚本(日常)+ Flyway(版本)Shell处理灵活操作,Flyway管理结构化变更

还有一个实操细节:不管用哪种方案,先在一个测试库上跑一遍。很多人就是跳过了这一步,直接把脚本扔到所有库上跑,结果SQL里有个语法错误,30个库全挂了。批量执行出错的时候,影响面是"所有库",不是"一个库"。

六、站群场景的特殊需求:不只是批量执行,是批量管理

站群的数据库批量执行有个特殊需求:不同站点可能需要执行不同的SQL。比如站点A、B、C刚上线需要全量初始化,站点D、E、F只需要更新一个配置表。这不是简单的"所有库跑同一个SQL",而是需要按站点分组、按标签过滤。

方案A:Shell脚本分组

在脚本里维护一个配置文件,把数据库名和所属分组对应起来。执行时根据分组选择不同的SQL目录。简单但维护成本随站点数增长。

方案B:数据库元信息表

每个站点的库里放一张site_meta表,记录站点类型、版本号、最后更新SQL时间。批量脚本先读meta表决定执行哪些SQL。自动化程度高,但初始设计需要一次投入。

方案C:系统化管理

用UC建站系统的内容中台统一管理多站数据库。系统层面维护站点分组和SQL版本状态,批量执行时自动匹配,不需要手工维护脚本里的站点列表。适合站点数超过50个的规模化场景。

不管是哪种方案,核心原则是一样的:批量执行的可追溯性比执行速度更重要。你至少要能回答三个问题:哪些库已经跑了?哪些库跑失败了?失败的原因是什么?如果这三个问题回答不了,批量执行就不是提效工具,是埋雷工具。

最后说一句:数据库批量执行这件事,工具选择不是最难的,最难的是养成"先在测试库验证、记录执行日志、保留回滚方案"这三个习惯。Shell脚本也好,Flyway也好,DataX也好,没有这三个习惯兜底,早晚会出一次让你后悔没做备份的事故。

相关推荐
在线客服
👇找客服拿折扣
QQ咨询&售后
在线时间
11:00 ~ 5:30
QQ:3155555535
👇联系QQ
👇联系WX
首页 程序 帮助 登录