linux系统中要实现一个导出MYSQL中指定表中2年前的数据的功能,有2种解决方案。
1。用SQL语句查询出数据,然后将用JAVA映射将不同的对象的属性值按照指定格式保存到指定目录的文件中。这种解决方法由于在保存数据到文件的时候用了JAVA映射,在性能方面肯定会比较慢,不过更符合面向对象的编程思想。
2。用mysqldump命令导出数据,保存到指定目录下。这种解决方法采用的是MYSQL的内部命令mysqldump实现的,保存的文件名和格式固定,性能比第一种方法好。由于项目需求对保存的文件名和格式并没有做限制,所以决定采用这种解决方案。
编程思路:a.从资源文件中读取出导出数据的表名(用逗号分隔),保存文件的目录,数据库连接的用户名和密码。
b.将以上参数组成mysqldump命令字符串。
例如:mysqldump -w"create_time<=date_add(sysdate(),INTERVAL -2 YEAR)" -uroot -plxlw99366 lpdb lp_sms
c.用Runtime对象执行该命令。
d.将Runtime执行的结果写入执行文件中。
首先将上面的命令到liunx服务器上执行,没有任何问题。在将JAVA代码上传到linux服务器的时候报错误:[数据备份错误输出][1]mysqldump: unknown option '-2'。真是奇怪,直接执行的时候解析mysqldump命令没有任何异常,用Runtime执行同样的命令就说不知道的操作'-2'。猜想可能是JAVA虚拟机执行命令时将' -2'解析成mysqldump的一个执行参数,所以就有以上的异常。想想就决定用JAVA将2年前的日期变成字符串再组成新的命令字符串:mysqldump -w"create_time<='2008-08-02'" -uroot -plxlw99366 lpdb lp_sms 。好了没有任何异常了,但是打开备份的文件一看,什么内容都有,就是没有数据。真是奇怪了,好在mysqldump导出的文件中有很详细的参数和执行流程。检查后发现在'--where "create_time<='2008-08-02'"'处多了双引号出来。于是修改代码将双引号去掉,再次上传代码到服务器测试。仍然没有数据。难道mysqldump的条件参数中的日期类型的字段不能直接和'2008-08-02'这样的字符串比较,这样的条件语句在Navicat工具中执行select * from lp_sms where create_time<'2008-08-02'是没有问题的。没办法只有先将create_time字段转成字符串再来比较了。改写JAVA代码生成如下命令:mysqldump -w-wdate_format(create_time,'%Y%m%d')<='2008-08-02' -uroot -plxlw99366 lpdb lp_sms,上传测试通过。这里还要注意一个地方,'2008--08-02'还不能写成'2008-08-02 00:00:00',否则会报错误无法访问的数据库'2008-08...。
总结以上处理过程,最大的结论就是在linux中用Runtime执行命令和直接在linux下执行命令还是有一些不同的,比如命令参数中带空格和'-'符号的时候就要特别注意了。还好无论怎么样问题还是解决。
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Calendar;
import java.util.Date;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.lx.ewm.ifc.DataMoveService;
import com.lx.ewm.tool.DateTimeUtil;
/**
*
* @ description:备份2年以上数据
* @ company lingxun
* @ author Lancelothe
* @ date 2010-7-27
*/
@Service("dataMoveService")
@Transactional
public class DataMoveServiceBean extends BaseServiceBean implements DataMoveService
{
/**
*
* @ description:用mysqldump命令将2年以前的数据导出保存到指定目录下。
* @ author Lancelothe
* @ parameter
* @ return void
* @ create_date 2010-7-27
* @ update_date 2010-7-27
* @param tableNames
*/
public void dataMove(String tableNames,String path,String baseComm)
{
String[] tableNameArr=tableNames.split(",");
StringBuffer comm;
// String fileName;
Runtime rt = Runtime.getRuntime();
Process process = null;
String date=DateTimeUtil.getDateTimeByParam(new Date(), "yyyyMMdd", Calendar.YEAR, -2);
try
{
for(int i=0;i<tableNameArr.length;i++)
{
comm=new StringBuffer();
// fileName=path+"/"+tableNameArr[i]+".txt";
File file=new File(path);
if(!file.exists())
{
file.mkdirs();
}
//修改文件目录的权限。否则后面的mysqldump命令将无法创建数据文件(*.txt)
rt.exec("chmod 777 "+path);
//生成命令
comm.append(baseComm);
comm.append(" lpdb ");
comm.append(tableNameArr[i]);
//-t表示不要创建表的DDL
//-c表示insert语句中带列名
//-l表示导出时锁定表
// comm.append(" -t -c -l");
/*
* 由于在linux下执行mysqldump命令时在带条件导出时,条件中不能包含空格和'-'符号,所以在对日期字段进行处理时必须按照以下格式进行。
*mysqldump -uroot -plxlw99366 lpdb lp_sms -t -c -l -wdate_format(create_time,'%Y%m%d')<='20080802'
*注意在-w后的参数也不能有双引号出现,虽然直接在Linux中执行该命令时可以带双引号。
*/
comm.append(" -wdate_format(create_time,'%Y%m%d')<='"+date+"'");
/*
* -T这个选项将会创建两个文件,一个文件包含DDL语句或者表创建语句,另一个文件包含数据。
*DDL文件被命名为table_name.sql,数据文件被命名为table_name.txt.路径名是存放这两个文件的目录。
*目录必须已经存在,并且命令的使用者有对文件的特权。
*/
comm.append(" -T"+path);
System.out.println("execu sql:"+comm.toString());
//执行命令
process=rt.exec(comm.toString());
// //保存命令执行结果
// file = new File(fileName);
// InputStream in = process.getInputStream();
// FileOutputStream out = new FileOutputStream(file);
// byte[] cache = new byte[2048];
// int length = in.read(cache);
// while (length != -1)
// {
// out.write(cache, 0, length);
// length = in.read(cache);
// }
// in.close();
// out.close();
//查看执行异常
InputStream error = process.getErrorStream();
BufferedReader errorbin = new BufferedReader(new InputStreamReader(error));
String info = errorbin.readLine();
int j = 0;
while (info != null)
{
System.out.println("[数据备份错误输出][" + (++j) + "]" + info);
info = errorbin.readLine();
}
errorbin.close();
error.close();
}
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}