这是前两天做的一个项目,主要功能就是把表A的数据,迁移到表B和表C,然后删除掉表A的数据。
限制就是,在表A中没有任何的标识列可以证明了该表的某行数据被操作过,并且,还在往表A中不停的插入数据。如果直接使用
代码语言:javascript复制insert into B(列1,列2,,,) select 列1,列2,,, from A
insert into C(列1,列2,,,) select 列1,列2,,, from A
delete from A
这样的语句进行插入时,在数据量小的时候,观察不出问题,但是使用脚本向表A中不停的插入数据量几十万的时候,就可以发现有数据丢失的问题。
进行修改,把抓取所有,改为抓取固定条数,来解决数据丢失的问题,如下:
代码语言:javascript复制insert into B (列1,列2,,,) select top 2000 列1,列2,,, from A
insert into C (列1,列2,,,) select top 2000 列1,列2,,, from A
delete from A WHERE EXISTS (SELECT '1' FROM B WHERE A.列1=B.列1);
在测试时发现,仍然有概率出现数据丢失的问题。猜测原因:A表在不停的插入数据中,执行插入语句1和插入语句2时,select top 2000的值可能存在差异,从而造成数据不一致的情况。
原因只是猜测,还需要进一步的验证,解决的方案就是将select top 2000放在一个临时表中,然后通过这临时表进行插入和删除的操作,如下:
代码语言:javascript复制create table #TMP(列1 类型1,列2 类型2,,,)
insert into #TMP(列1 类型1,列2 类型2,,,) select top 2000 列1,列2,,, from A with(nolock)
insert into B(列1,列2,,,) select 列1,列2,,, from #TMP with(nolock)
insert into C(列1,列2,,,) select 列1,列2,,, from #TMP with(nolock)
delete from A WHERE EXISTS (SELECT '1' FROM #TMP with(nolock) WHERE A.列1=#TMP.列1);
通过一个临时表来存放数据后,在通过脚本向表A中插入百万级的数据量的同时,执行数据的迁移操作无数据丢失的情况发生,数据得到了正常迁移。
注:以上的SQL为存储过程,程序通过调用存储过程来执行数据迁移操作