批量执行 SQL 脚本的 Shell 脚本及注意事项
脚本示例
bash
#!/bin/bash
# 配置数据库和用户信息
DATABASES=("Database1" "Database2" "Database3" "Database4" "Database5")
USERS=("user1" "user2" "user3" "user4" "user5" "user6")
PASSWORD="your_password" # 假设所有用户使用同一个密码
SQL_SCRIPT="upgrade_script.sql" # SQL 脚本路径
# 数据库执行函数
execute_sql() {
local db=$1
local user=$2
local sql=$3
echo "Executing script on database: $db, user: $user..."
mysql -h localhost -u "$user" -p"$PASSWORD" "$db" < "$sql"
if [[ $? -ne 0 ]]; then
echo "Error: Execution failed on $db for user $user" >&2
return 1
fi
echo "Success: Executed script on $db for user $user"
}
# 主循环:对每个数据库和用户执行 SQL
for db in "${DATABASES[@]}"; do
for user in "${USERS[@]}"; do
execute_sql "$db" "$user" "$SQL_SCRIPT"
done
done
echo "All scripts executed successfully!"
工作流程
-
配置部分:
DATABASES
列出所有目标数据库。USERS
列出所有需要执行 SQL 脚本的用户。PASSWORD
是用户的统一密码,脚本使用-p
参数传递密码。SQL_SCRIPT
是 SQL 脚本的文件路径。
-
函数定义:
execute_sql
函数通过mysql
命令连接数据库并执行脚本。- 检查命令返回值
$?
,如有错误会输出失败信息到标准错误。
-
主循环:
- 外层循环遍历每个数据库。
- 内层循环遍历每个用户。
- 对每个
数据库-用户
执行execute_sql
函数。
-
日志记录:
- 在执行脚本时打印执行进度。
- 成功和失败的信息分别输出到标准输出和标准错误。
注意事项
-
SQL 脚本的幂等性:
- 确保 SQL 脚本是幂等的(多次执行不会产生重复影响)。
- 如果需要,可以在 SQL 脚本中添加
IF NOT EXISTS
等判断条件。
-
数据库和用户权限:
- 确保所有用户对目标数据库有执行权限,否则会出现权限错误。
-
MySQL 密码管理:
-
脚本中密码明文存储可能存在安全风险,可以改用
.my.cnf
文件来管理凭据:plaintext[client] user=user1 password=your_password
然后调用时简化为:
bashmysql Database1 < upgrade_script.sql
-
-
脚本执行路径:
- 确保脚本执行时,
SQL_SCRIPT
文件路径正确。如果脚本运行在不同目录,建议使用绝对路径。
- 确保脚本执行时,
-
执行错误处理:
- 如果一个数据库或用户执行失败,建议脚本继续运行,记录失败的数据库和用户,以便后续重试。
-
多线程优化(可选):
-
如果数据库和服务器性能允许,可以使用
&
并发执行以提高效率:bashfor db in "${DATABASES[@]}"; do for user in "${USERS[@]}"; do execute_sql "$db" "$user" "$SQL_SCRIPT" & done done wait
-
可能遇到的问题
-
脚本执行失败:
- 原因:脚本内容不正确、数据库用户无权限、网络问题等。
- 解决:查看失败日志,修正 SQL 脚本或用户权限。
-
MySQL 执行超时:
- 如果脚本非常大或查询耗时长,可能会出现超时问题。
- 解决:在 MySQL 中调整
max_allowed_packet
和wait_timeout
参数。
-
密码泄露风险:
- 密码明文存储在脚本中存在安全隐患。
- 建议改用
.my.cnf
或环境变量存储密码。
-
并发执行的冲突:
- 并发运行可能导致锁表或资源竞争。
- 解决:控制并发数量,或按顺序逐一执行。
为所有用户授予数据库执行权限的操作指南
步骤 1:明确权限需求
- 确认需要授予的权限类型。对于执行 SQL 脚本的需求,通常需要
EXECUTE
或其他相关权限(如SELECT
,UPDATE
,INSERT
,DELETE
)。 - 确认哪些用户需要权限。
步骤 2:SQL 语法示例
假设目标数据库名为 target_db
,需要为 5 个数据库中的每个数据库的 6 个用户授予权限,以下是通用的 GRANT
语法:
sql
USE target_db;
-- 示例:为用户 user1 授予 EXECUTE 权限
GRANT EXECUTE ON DATABASE target_db TO user1;
-- 示例:如果还需要 SELECT、INSERT 权限:
GRANT SELECT, INSERT, UPDATE, DELETE ON DATABASE target_db TO user1;
步骤 3:为所有用户批量授予权限
假设有多个用户和多个数据库,可以用脚本循环处理,以下是手动 SQL 示例:
sql
-- 在目标数据库下为每个用户循环授予权限
USE target_db;
GRANT EXECUTE ON DATABASE target_db TO user1;
GRANT EXECUTE ON DATABASE target_db TO user2;
GRANT EXECUTE ON DATABASE target_db TO user3;
GRANT EXECUTE ON DATABASE target_db TO user4;
GRANT EXECUTE ON DATABASE target_db TO user5;
GRANT EXECUTE ON DATABASE target_db TO user6;
步骤 4:使用 Shell 脚本批量执行 GRANT
脚本内容
假设我们使用 mysql
客户端登录来批量执行这些 SQL 授权操作:
bash
#!/bin/bash
# 数据库配置
HOST="localhost"
USER="root"
PASSWORD="your_password"
# 数据库和用户列表
DATABASES=("db1" "db2" "db3" "db4" "db5")
USERS=("user1" "user2" "user3" "user4" "user5" "user6")
# 授权脚本
for DB in "${DATABASES[@]}"; do
for USER in "${USERS[@]}"; do
echo "Granting EXECUTE privilege on $DB to $USER..."
mysql -h "$HOST" -u "$USER" -p"$PASSWORD" -e "GRANT EXECUTE ON $DB.* TO '$USER';"
done
done
echo "All privileges granted!"
注意事项
-
权限验证:
- 确保目标用户在数据库中已经存在。如果用户不存在,需要先通过
CREATE USER
创建用户。
sqlCREATE USER 'user1'@'localhost' IDENTIFIED BY 'password';
- 确保目标用户在数据库中已经存在。如果用户不存在,需要先通过
-
FLUSH PRIVILEGES
:- 有些数据库需要在权限更新后运行
FLUSH PRIVILEGES
来刷新权限表。
sqlFLUSH PRIVILEGES;
- 有些数据库需要在权限更新后运行
-
权限范围:
- 如果只需要对特定表授予权限,可以用
GRANT EXECUTE ON db_name.table_name
。
- 如果只需要对特定表授予权限,可以用
-
错误处理:
- 如果脚本中出现
Access Denied
错误,可能是当前执行脚本的用户权限不足。请确保脚本运行用户拥有足够权限(如GRANT OPTION
权限)。
- 如果脚本中出现
-
重复授权:
- MySQL 和其他数据库通常不会因为重复执行
GRANT
而出错,因此可以放心批量执行脚本。
- MySQL 和其他数据库通常不会因为重复执行
常见问题
-
用户不存在错误:
- 需要确保所有用户已被创建。如果需要自动创建用户,可以扩展 Shell 脚本,添加
CREATE USER
。
- 需要确保所有用户已被创建。如果需要自动创建用户,可以扩展 Shell 脚本,添加
-
权限不足:
- 确保运行脚本的用户(如
root
)具有GRANT OPTION
权限。
- 确保运行脚本的用户(如
-
多数据库环境:
- 如果存在多个数据库,确保用户被授予所有需要的数据库权限。