BCP IN出错回滚及错误捕捉

 
最近开发了一个小系统,遇到了很多的困难,曾经在网上试图收集了一部份解决资料,但都无功而返,只好把问题点发到论坛上大家一起研究,现在,我就把一些问题点及解决方法总结一下。
 
首先十分感谢在我工作生活中给我很大帮助的三大论坛及论坛中的各位老师:
1.    CSDN社区中心     http://community.csdn.net/
 
2.    中国DOS联盟      http://www.cn-dos.net/forum/index.php
 
3.    51CTO技术论坛    http://bbs.51cto.com/
                                                     ZYZ0304360(稳,勤学)
希望大家常去看看
 
由于语文学得不好,如有影响理解之处,还请大家见谅:
新系统开发遇到的问题以及解决方法
开发时,BCPIN的问题要远远多于BCPOUT,因为毕竟BCPIN实现的功能对数据库中的对象有所改动。
 
问题1:BCPIN回滚问题
BCP中有一个参数 -b
MS-SQLSERVER2000是这样描述的:
-b batch_size
指定所复制的每批数据中的行数。每个批处理作为一个事务复制至服务器。SQL Server 提交或回滚(在失败时)每个批处理的事务。默认情况下,指定的数据文件中的所有数据都作为一批复制。
也就是说
BCPIN 会把一次导入-b参数行的数据作为一个事务,由于事务具有原子性(事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。)所以,一旦导入出错,整个事务回滚。而在-b默认情况下,指定的数据文件中的所有数据都作为一批复制。也就是说-b默认情况下,BCPIN会把全部数据的导入作为一个事务,所以在BCPIN时,不加-b参数时,如果导入出错,则数据全部回滚。
例:
两张同样的表(字段,主键都相同):table1,table2
BCP “select top 200 * from dbdaily..table1 union all select top 200 * from dbdaily..table1” queryout “table.dat” -S. -Usa -P -n -q 
 
1.有-b参数
BCP “dbdaily..table2”in “table.dat” -S. -Usa -P -n -q -b30
执行后倒入了180条,因为每30条作为一个事务进行导入,在第180条到210条是出错(主键重复),此事务回滚,前6次共导入180条数据
 
2.无-b参数
BCP “dbdaily..table2”in “table.dat” -S. -Usa -P -n -q
执行后导入了0条数据,无-b情况下所有数据的导入作为一个事务,(导入的速度特别快,因为不需要像有-b那样每次都停顿等待事务提交,但是数据全部导入之后的事务提交是很慢的。)在第201条数据导入时主键重复,数据全部回滚。(事务原子性)
 
 
问题2:BCPIN错误信息捕捉
 
还是用相同的例子
@echo off
 
echo _____________begin_____________ >>test.log
date /T >>test.log
time /T >>test.log
 
 
BCP “select top 200 * from dbdaily..table1 union all select top 200 * from dbdaily..table1” queryout “table.dat” -S. -Usa -P -n -q
 
BCP “dbdaily..table2”in “table.dat” -S. -Usa -P -n -q
if errorlevel 1 goto :error
 
 
goto :end
 
:error
time /T >>test.log
echo here is an error >>test.log
goto :end
 
:end
time /T >>test.log
echo end >> test.log
echo ___________________BYE_______________>>test.log
 
此批处理中,BCPIN出现的主键重复错误是无法用errorlevel捕捉到的,无论BCPIN执行成功或失败errorlevel都是0。微软已经承认这个是微软公司的产品问题(详见: http://support.microsoft.com/kb/922660/en-us
 
所以我们不得不想另外一种方法来捕捉BCPIN的错误信息,本人曾经试过很多方法,失败了太多次,终于找到了解决方法
 
解决方法如下:
1.      将BCPIN的内容生成文本文件(.txt .log)在文件中查找相应错误信息字符串,如果文件中有错误信息字符串,则跳转到:error。
 
BCP “dbdaily..table2”in “table.dat” -S. -Usa -P -n -q >>ErrGet.txt
Type ErrGet.txt| findstr "Error = "&&goto :error
(或者
Type ErrGet.txt| findstr "SQLState = 23000, NativeError = 2627"&&goto :error
2627是主键重复的错误号)
 
在最后:end可以删掉ErrGet.txt
:end
if exist ErrGet.txt del /f ErrGet.txt
 
 
(午睡刚醒,不清醒。。。)
 
2.      直接在命令行解释器中捕捉反馈信息,每次执行时,BCP的执行相关信息,都会显示在命令行解释器中,直接捕捉错误反馈信息的关键字符串。
 
BCP “dbdaily..table2”in “table.dat” -S. -Usa -P -n -q |find /i "Error = "&&goto :error
 
好了,有这两个方法就够用了,虽然说原理是一样的,但用法是因人而异,因系统而异的。
 
 
问题3
开发时,上面是两个相对来说大一点的问题
现在,整理一些细琐的
 
(1) 批处理中的延时设置
Ping 127.0.0.1 -n 6 >nul
-n 后面的6 自己改,上面的例子延时5秒(6-1=5)
 
(2) 备份日志文件
备份时,需要精确到分钟
 
例:
Set folder_bk=D:/NEWSYStest/
copy test.log %date:/=%%time:~0,2%%time:~3,2%test.log
del test.log
在小时是两位数(10点到24点)时是对的,是个位数是就错了
例如,当前时间2008/01/12 09:50:35.345
 
备份后的文件名应该是200801120950test.log
但,用上面的例子就会出错 原因是无法生成中间有空格的文件名20080112 950test.log
 
解决方法:
把空格替换成0
Set folder_bk=D:/NEWSYStest/
set newtime=%date:/=%%time:~0,2%%time:~3,2%
copy test.log %folder_bk%%newtime: =0%test.log
del test.log
 
%newtime: =0%此处“ =0”是把空格替换成0
生成200801120950test.log
 
或者
在目标文件名上加“”
Set folder_bk=D:/NEWSYStest/
copy test.log “%folder_bk%%date:/=%%time:~0,2%%time:~3,2%test.log”
del test.log
 
生成20080112 950test.log(注:2和9之间有空格)
 
。。。。。。
 
新系统的功能是:
在A地B地无法直接数据传输的情况下:
在A地,用BCP取出数据传送到FTP上,
在B地,在FTP上取下数据导入数据库
 
A地:BCPOUT > MAKECAB >FTP   >DEL
B地:FTP       > EXPAND  >BCPIN >BACKUP >DEL
全部每天自动执行,有任何一步出错,自动给负责系统的人发邮件,要求检查数据,邮件的内容为出错时的信息,附带日志文件及ERROR日志
由于是公司财产,所以无法与大家分享,
但如果有在开发过程中有此类困难的朋友,我可以帮助您
邮件: saintasia@163.com
OVER
 
                                                                             2008/01/12
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值