其实批量导入导出数据很常见了,可以参考我之前写的博客mysql数据库导入导出
简单的文件导入导出没问题,但是生活总是惊喜连连,突然叫我们迁移一个之前非常大的一个系统,给了一个压缩包5百多M,解压缩之后5.6G的文件夹
,里面有27个*.sql文件
,我开始以为是一个数据库里面的27张表,结果是27个数据库
…,这还是删减过后的文件
问题分析
27个数据库
就意味着不可能一次执行完成,因为要切换数据库,甚至要先创建数据库。
好吧,手动单个运行是不可能的,程序员怎么可能重复操作27次呢?
而且文件拖到dategrip里面,然后右键选择数据库,点击运行,一个文件大概运行几分钟,重复的工作为什么不使用程序完成呢?。
其实主要是不用在隔一会儿来看下是否完成了,可以安心的等待数据导入完成
,这是不是很棒👍🏻的体验呢?
先来连接测试
mysql -hrm-xxx.mysql.rds.aliyuncs.com -uxx -pxxx
发现一个问题,密码中带有特殊字符@
提示event not found: @xx
怎么办,加个引号表示这是密码就好了
mysql -hrm-xxx.mysql.rds.aliyuncs.com -uxx -p'xxx'
测试成功
然后尝试导入一个(数据库先建)
注意导入的时候是mysql
不是mysqldump
mysql -hrm-xxx.mysql.rds.aliyuncs.com -uxx -p'xxx' -D xx <xx.sql
一些导入的问题
报错,发现是数据库账号权限不够
ERROR 1044 (42000): Access denied for user 'xx'@'%' to database 'xx'
联系老板换了root的账号
一个警告,不影响,含义是我们不要用明文在命令行执行
,因为用history是可以查看历史命令的。
mysql: [Warning] Using a password on the command line interface can be insecure.
继续报错,这个错误困扰了我
ERROR 1227 (42000) at line 904: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
翻译过来是你至少需要一个超级权限
,但是账号都是root了怎么还会权限不够呢?
后面查询资料是不支持这个语法
,可以全局搜索一下删除掉关键字DEFINER
相关的行,然后就ok了。
/*!50013 DEFINER=`xxx`@`%` SQL SECURITY DEFINER */
开始导入
其实我开始想的是使用Java执行命令导入,因为可以方便的拼接字符串,(数据库是文件名),但是执行Runtime类之后发现很麻烦,特别是环境配置
多方尝试之后,还是采用了shell
脚本的方式执行,毕竟这个场景处理非java之长。
本地已经可以执行导入的情况下,其实只需要拼接一下导入数据的语句就好了
不卖关子了,直接贴核心代码。
编写代码就是要让小白也能看懂,嘿嘿,还不快来关注我~
#!/bin/bash
echo hello;
ls
echo $PATH
export PATH=$PATH:/opt/homebrew/Cellar/mysql@5.7/5.7.34/bin
#source ~/.bash_profile
cd mysqldump
for i in `ls`
do
#操作文件
dbName=${i//.sql/''}
echo "start "${dbName}
mysql -hrm-xxx.mysql.rds.aliyuncs.com -uroot -p'xxx!' -D${dbName} < ${i}
done
其实非常简单,但是就是这一点点东西花费了我小半天的功夫。
核心代码详解
#!/bin/bash
echo hello;
ls
脚本都是#!/bin/bash
开头第一行,表示是一个脚本,使用/bin/bash来执行命令。
echo hello;
ls
这两行是测试脚本是否正常工作,输出字符串hello,然后执行ls命令。这两个是调试代码可以删除,不影响代码执行。
导入环境变量
echo $PATH
export PATH=$PATH:/opt/homebrew/Cellar/mysql@5.7/5.7.34/bin
#source ~/.bash_profile
一直报找不到mysql命令,就导入下环境变量,或者source ~/.bash_profile
刷新一下环境变量获取到最新的环境变量。不然会提示mysql命令找不到。
循环核心
for i in `ls`
do
#操作文件
done
这就是最常用的循环了,一般都是ls命令,然后遍历文件名用的最多,会了这个,你遇到的大部分问题都可以解决了。
``包住的就表示是命令行命令,会执行,其实用这个包住字符串也可以执行哦。
核心拼接命令
dbName=${i//.sql/''}
echo "start "${dbName}
mysql -hrm-xxx.mysql.rds.aliyuncs.com -uroot -p'xxx!' -D${dbName} < ${i}
看起来最简单的就是这个了,定义好变量然后直接替换到指定位置就可以了,首选要替换文本,很简单就是把后缀去掉就好了
所以${i//.sql/''}
翻译一下
就是${i}
变量i,//
替换 .sql
替换的文本/''
替换后的文本为空字符串。
组合起来就是把变量i中的所有.sql文本替换成空字符串,//
是替换所有 一个/
是替换一次。