Perl访问MSSQL并迁移到MySQL数据库脚本实例
Linux下没有专门为MSSQL设计的访问库,不过介于MSSQL本是从sybase派生出来的,因此用来访问Sybase的库自然也能访问MSSQL,FreeTDS就是这么一个实现。
Perl中通常使用DBI来访问数据库,因此在系统安装了FreeTDS之后,可以使用DBI来通过FreeTDS来访问MSSQL数据库,例子:
usingDBI;
my$cs="DRIVER={FreeTDS};SERVER=主机;PORT=1433;DATABASE=数据库;UID=sa;PWD=密码;TDS_VERSION=7.1;charset=gb2312";
my$dbh=DBI->connect("dbi:ODBC:$cs")ordie$@;
因为本人不怎么用windows,为了研究QQ群数据库,需要将数据从MSSQL中迁移到MySQL中,特地为了QQ群数据库安装了一个WindowsServer2008和SQLServer2008r2,不过过几天评估就到期了,研究过MySQL的Workbench有从MSSQLServer迁移数据的能力,不过对于QQ群这种巨大数据而且分表分库的数据来说显得太麻烦,因此写了一个通用的perl脚本,用来将数据库从MSSQL到MySQL迁移,结合bash,很方便的将这二十多个库上百张表给转移过去了,Perl代码如下:
#!/usr/bin/perl
usestrict;
usewarnings;
useDBI;
die"Usage:qqdb\n"if@ARGV!=1;
my$db=$ARGV[0];
print"Connectintodatabases$db...\n";
my$cs="DRIVER={FreeTDS};SERVER=MSSQL的服务器;PORT=1433;DATABASE=$db;UID=sa;PWD=MSSQL密码;TDS_VERSION=7.1;charset=gb2312";
subdb_connect
{
my$src=DBI->connect("dbi:ODBC:$cs")ordie$@;
my$target=DBI->connect("dbi:mysql:host=MySQL服务器","MySQL用户名","MySQL密码")ordie$@;
return($src,$target);
}
my($src,$target)=db_connect;
print"Readingtableschemas....\n";
my$q_tables=$src->prepare("SELECTnameFROMsysobjectsWHERExtype="U"ANDname!="dtproperties";");#获取所有表名
my$q_key_usage=$src->prepare("SELECTTABLE_NAME,COLUMN_NAMEfromINFORMATION_SCHEMA.KEY_COLUMN_USAGE;");#获取表的主键
$q_tables->execute;
my@tables=();
my%keys=();
push@tables,@_while@_=$q_tables->fetchrow_array;
$q_tables->finish;
$q_key_usage->execute();
$keys{$_[0]}=$_[1]while@_=$q_key_usage->fetchrow_array;
$q_key_usage->finish;
#获取表的索引信息
my$q_index=$src->prepare(qq(
SELECTT.name,C.name
FROMsys.index_columnsI
INNERJOINsys.tablesTONT.object_id=I.object_id
INNERJOINsys.columnsCONC.column_id=I.column_idANDI.object_id=C.object_id;
));
$q_index->execute;
my%table_indices=();
while(my@row=$q_index->fetchrow_array)
{
my($table,$column)=@row;
my$columns=$table_indices{$table};
$columns=$table_indices{$table}=[]ifnot$columns;
push@$columns,$column;
}
$q_index->finish;
#在目标MySQL上创建对应的数据库
$target->do("DROPDATABASEIFEXISTS`$db`;")ordie"Cannotdropolddatabase$db\n";
$target->do("CREATEDATABASE`$db`DEFAULTCHARSET=utf8COLLATEutf8_general_ci;")ordie"Cannotcreatedatabase$db\n";
$target->disconnect;
$src->disconnect;
my$total_start=time;
formy$table(@tables)
{
my$pid=fork;
unless($pid)
{
($src,$target)=db_connect;
my$start=time;
$src->do("USE$db;");
#获取表结构,用来生成MySQL用的DDL
my$q_schema=$src->prepare("SELECTCOLUMN_NAME,IS_NULLABLE,DATA_TYPE,CHARACTER_MAXIMUM_LENGTHfromINFORMATION_SCHEMA.COLUMNSwhereTABLE_NAME=?ORDERBYORDINAL_POSITION;");
$target->do("USE`$db`;");
$target->do("SETNAMESutf8;");
my$key_column=$keys{$table};
my$ddl="CREATETABLE`$table`(\n";
$q_schema->execute($table);
my@fields=();
while(my@row=$q_schema->fetchrow_array)
{
my($column,$nullable,$datatype,$length)=@row;
my$field="`$column`$datatype";
$field.="($length)"if$length;
$field.="PRIMARYKEY"if$key_columneq$column;
push@fields,$field;
}
$ddl.=join(",\n",@fields);
$ddl.="\n)ENGINE=MyISAM;\n\n";
$target->do($ddl)ordie"Cannotcreatetable$table\n";
#创建索引
my$indices=$table_indices{$table};
if($indices)
{
for(@$indices)
{
$target->do("CREATEINDEX`$_`ON`$table`(`$_`);\n")ordie"Cannotcreateindexon$db.$table$.$_\n";
}
}
#转移数据
my@placeholders=map{"?"}@fields;
my$insert_sql="INSERTDELAYEDINTO$tableVALUES(".(join",",@placeholders).");\n";
my$insert=$target->prepare($insert_sql);
my$select=$src->prepare("SELECT*FROM$table;");
$select->execute;
$select->{"LongReadLen"}=1000;
$select->{"LongTruncOk"}=1;
$target->do("SETAUTOCOMMIT=0;");
$target->do("STARTTRANSACTION;");
my$rows=0;
while(my@row=$select->fetchrow_array)
{
$insert->execute(@row);
$rows++;
}
$target->do("COMMIT;");
#结束,输出任务信息
my$elapsed=time-$start;
print"Childprocess$$fortable$db.$tabledone,$rowsrecords,$elapsedseconds.\n";
exit(0);
}
}
print"Waitingforchildprocesses\n";
#等待所有子进程结束
while(wait()!=-1){}
my$total_elapsed=time-$total_start;
print"Alltasksfrom$dbfinished,$total_elapsedseconds.\n";
这个脚本会根据每一个表fork出一个子进程和相应的数据库连接,因此做这种迁移之前得确保目标MySQL数据库配置的最大连接数能承受。
然后在bash下执行
forxin{1..11};do./qq.plQunInfo$x;done
forxin{1..11};do./qq.plGroupData$x;done
就不用管了,脚本会根据MSSQL这边表结构来在MySQL那边创建一样的结构并配置索引。
相关文章
- 存储图片资源:MySQL数据库实现(mysql存图片类型)
- MySQL 监控:轻松掌握数据库状态(mysql监控软件)
- 字符串MySQL中使用SUBSTRING函数截取字符串(mysql截取)
- MySQL数据库实时监控解决方案(mysql数据库监控工具)
- MySQL二进制日志:灵活的备份和恢复策略(mysql二进制日志)
- 用MySQL实现数据类型转换(mysql转换数据类型)
- MySQL数据库可视化:简化你的操作(mysql数据库可视化工具)
- MySQL中文在线手册:助你更轻松上手数据库管理(mysql中文在线手册)
- MySQL查询次数有多少?(mysql查询次数)
- MySQL主从复制的工作原理详解(mysql的主从原理)
- 从 Python 连接到 MySQL:实现更多强大的数据库应用(python和mysql)
- MySQL字符串索引:高效管理数据库(mysql字符串索引)
- MySQL索引详解作用类型创建与使用(mysql中什么叫索引)
- MySQL使用DATE语句查询日期数据(mysql中date语句)
- C和MySQL的结合应用实例研究(c++ mysql 实例)
- 绑定MySQL让你的数据库管理更简单(bind mysql)
- 数据库Cmd命令行快速导入MySQL数据库(cmd 导入mysql)
- MySQL导出Excel文件(xlsx)时遇到错误的解决方法(mysql xlsx出错)
- 同一数据库,不同服务器,MySQL有何不同(mysql不同服务器吗)
- MySQL大全深入探索SQL关键字,不包含用法详解(mysql 不包含用法)
- 如何选择适合自己的 MySQL 版本(mysql 下载哪一版)
- 避免繁琐的语名,轻松实现MySQL建表(mysql不用语名建表)