使用mysqldump命令生成SQL脚本

目录

1、mysqldump.exe

2、Java实现批量生成SQL脚本

3、bat批处理文件实现数据库备份


1、mysqldump.exe

mysqldump.exe文件是MySQL的一个命令文件,在安装目录MySQL Server 5.6\bin下可以找到。

此次分享的两个例子都是基于mysqldump命令,关于该命令的具体作用和参数可自行百度查阅材料。

笔者亲测,可以在没有安装MySQL的电脑使用该命令,只需将mysqldump.exe文件下载/拷贝到电脑中即可。

下面我通过一个简单的例子来简单演示下mysqldump的使用。

首先,先在测试数据库建一个表,插入数据:

create table test.t_dict(
dict_code varchar(32) not null,
dict_name varchar(64) not null,
PRIMARY KEY (dict_code) USING BTREE
);

insert into test.t_dict(dict_code,dict_name) values('test1','测试1');
insert into test.t_dict(dict_code,dict_name) values('test2','测试2');

假设我们的mysqldump.exe文件在D盘根目录下,进入cmd,执行以下命令:

mysqldump -h你的数据库服务器IP -u账号 -p密码 --lock-tables=0 --compact --no-create-info --skip-comments test t_dict > D:/t_dict_20210721.sql

 执行完毕后,可以在D盘找到生成的SQL文件:t_dict_20210721.sql

打开文件:

 

2、Java实现批量生成SQL脚本

场景:系统上线,需要同步数据库的数据到生产数据库,除了第一次是全量同步,后续的迭代都是增量,主要由于开发/测试环境有很多测试数据,如果全量同步,会造成数据异常,因此每次发布需要找出当次发布的数据,精准同步数据。

以test.t_dict为例,假如本次发布只需要更新dict_code='test1'这条记录,我们其实只需生成该条记录即可,最主要是使用mysqldump命令中的-w参数,参数值就是where条件,以这个为例子,我们可以在cmd单独执行下:

mysqldump -h你的MySQL数据库IP -u账号 -p密码 --lock-tables=0 --compact --no-create-info --skip-comments test t_dict -w"dict_code='test1'" > D:/t_dict_20210721.sql

以上就是基本原理。

但实际中我们是要同步不同表的数据,在这种情况下,使用mysqldump命令每次只能生成一张表的数据。

基本思路:首先整理所有查询SQL的语句放到指定文件,Java读取文件,存到字符串,将语句分拆成单独的每一条查询SQL,然后循环使用命令行生成每张表的insert脚本,最后将所有insert脚本汇总。

以下是完整实现代码:

package com.util;

import org.apache.commons.lang3.StringUtils;


public class MySQLUtil {

	public static void main(String argsp[])
	{
	    String basepath =MySQLUtil.class.getResource("").toString();  
		String ssql_file_path=basepath.replace("file:/", "")+"query_sql.txt";
		String sql_segs=FileUtil.getStringFromFile(ssql_file_path);
		String []sql_seg_arr=sql_segs.split(";");
		String migrate_sql_file_dir_path="D:/workspace/demo/src/java/com/util";
		String ms_str="";
		for(String per_seg : sql_seg_arr)
		{
			if(!StringUtils.isEmpty(per_seg.replaceAll("\\r\\n", "")))
				{
			per_seg.indexOf("where");
			String seg_from=per_seg.substring(0,per_seg.indexOf("where"));
			String seg_where=per_seg.substring(per_seg.indexOf("where")+6);
			String cmd = "cmd /c C:/mysqldump -h你的数据库IP -u账号 -p密码 --lock-tables=0 --compact --no-create-info --skip-comments 你的MySQL库名 "; 
			String tf=migrate_sql_file_dir_path+"/"+seg_from.split("from")[1].trim()+"_"+Math.round(Math.random()*10000)+".sql";
			cmd=cmd+seg_from.split("from")[1].trim()+" -w\""+seg_where.replaceAll("\\r\\n", "")+"\" > "+tf;
			
			
	        try {
	        	Process child = Runtime.getRuntime().exec(cmd);
	        	int tag = child.waitFor();// 等待进程终止  
			} catch (Exception  e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}  
	        System.out.println(cmd);
	        ms_str+=FileUtil.getStringFromFile(tf);
				}
		}
		ms_str = ms_str.replaceAll("SET @(.+);", "");
		System.out.println(ms_str);
		FileUtil.wirteStringToFile(migrate_sql_file_dir_path+"/insert.sql", ms_str);
	}
	
}
package com.common.util;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;

/**
文件操作实体类
*/
public class FileUtil {

	/* 往文件写入字符串 */
	public static void wirteStringToFile(String path, String context) {
		OutputStreamWriter osw = null;
		try {
			File file = new File(path);
			if (!file.exists()) {
				file = new File(file.getParent());
				if (!file.exists()) {
					file.mkdirs();
				}
			}

			osw = new OutputStreamWriter(new FileOutputStream(path), System.getProperty("file.encoding"));
			osw.write(new String(context.getBytes(), System.getProperty("file.encoding")));
			osw.flush();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (osw != null) {
					osw.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/* 读取文件中的字符串 */
	public static String getStringFromFile(String path) {
		String data = null;
		// 判断文件是否存在
		File file = new File(path);
		if (!file.exists()) {
			return data;
		}
		// 获取文件编码格式
		String code = getFileEncode(path);
		InputStreamReader isr = null;
		try {
			// 根据编码格式解析文件
			if ("asci".equals(code)) {
				// 这里采用GBK编码,而不用环境编码格式,因为环境默认编码不等于操作系统编码
				// code = System.getProperty("file.encoding");
				code = "GBK";
			}
			isr = new InputStreamReader(new FileInputStream(file), code);
			// 读取文件内容
			int length = -1;
			char[] buffer = new char[1024];
			StringBuffer sb = new StringBuffer();
			while ((length = isr.read(buffer, 0, 1024)) != -1) {
				sb.append(buffer, 0, length);
			}
			data = new String(sb);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (isr != null) {
					isr.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return data;
	}

}

3、bat批处理文件实现数据库备份

场景:由于新上线的一个项目,开发人员没有控制好delete的删除条件,在某种情况下会导致删除表的全部数据,由于表格数据更新不频繁,因此在bug修复前,先通过每天自动备份,以免数据再次丢失。

以下是实现代码:

@echo off

rem 脚本使用配置开始=======================start
::设置数据库所在ip
set ip=数据库所在ip
::设置数据库端口
set port=数据库端口
::设置数据库连接用户(为了保证导出函数,视图,存储过程,触发器请给用户设置权限)
set user=账号
::设置数据库连接用户密码(密码中的%需要两个%%转义)
set password="密码"
::设置备份文件存储位置
set dataFolder=D:/mysql_backup
::设置压缩软件WinRAR的安装目录
set winrarPath="C:\Program Files\WinRAR"
::设置MySQL的安装目录的安装目录
set mysqlPath="D:\Program Files\MySQL\MySQL Server 5.6\bin"
::设置备份日期
set curdate=%date:~0,4%%date:~5,2%%date:~8,2%
rem 脚本使用配置结束=======================end



echo 开始备份=======

%mysqlPath%\mysqldump.exe -R -u%user% -p%password% -h%ip% -P%port% 需要备份的数据库名 > %dataFolder%/backup_%curdate%.sql

rem 压缩备份文件
::若压缩文件存在,先删除
if exist "%dataFolder%/nonauto_backup_%curdate%.rar" (
    del %dataFolder%/nonauto_backup_%curdate%.rar
)
::使用WinRAR压缩文件并删除源文件
echo 开始压缩=======
%winrarPath%\Rar.exe a -k -r -s -m5 -ep1 -df %dataFolder%/nonauto_backup_%curdate%.rar %dataFolder%/backup_%curdate%.sql

echo 备份结束

设置定时任务,可以参考我的另一篇博客:定时执行kettle任务


版权声明:本文为lcsjdn原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。