场景:

我们导入MR数据时发现磁盘空间不够用了,导致的结果就是我们的程序很可能会抛出异常了,我们需要导入数据的时候进行日志瘦身。

问1:导入数据的时候,瘦身是否会造成数据库的异常?

 

DBA提供解决方案:

回答问1:

没有问题。不会产生冲突。不过要给日子预留空间,防止被填满。

 

 1. 确认M_Develop 的恢复模式是否为简单simple。

查看脚本如下。

     

select recovery_model_desc,name
         from sys.databases
         where name='M_Develop'

 

2. 如果不是simple。请改为simple

修改脚本如下:

USE [master]
GO
ALTER DATABASE [M_Develop] SET RECOVERY SIMPLE WITH NO_WAIT
GO。

 

3.恢复模式为simple之后。确认日志大小,和占用百分比:脚本如下:

 

dbcc sqlperf(logspace)

 

 

sql server always on清理日志 sql清理日志文件_数据库

4.如果数据库是simple之后,log space used(%)   日志占比应该比较小。

 

5.收缩日志文件大小

 

use M_Develop
go
 
--找到库的日志文件名称
select name
from sys.database_files
where type_desc='log'

 

--缩小日志,假设上述查询结果日志名为M_Develop_log,收缩至10G,那么脚本如下

dbcc shrinkfile (M_Develop_log,10240)
 
--再次检查日志量大小
dbcc sqlperf(logspace)

 

(备注:其中将数据库模式改为simple是为了性能考虑。如果不更改,那么需要备份日志,backup log。不推荐)

 

解决多线程改写问题

当我们改为多线程之后,之前DBA给提出使用单独的表来站位对应的MR表的OID,防止多线程在执行BulkCopy相关存储过程中出现抢占同一个OID,导致出现异常:

存储过程

操作源数据

使用的站位表

BulkCopyTempM1ToM1_0

ImportTemp_M1_01

M1及其相关子表

M1_M2及其相关子表

Global_MaxM1OID

Global_MaxM1_M2OID

BulkCopyTempM2ToM2_0

ImportTemp_M2_01

M1及其相关子表

M1_M2及其相关子表

Global_MaxM2OID

Global_MaxM1_M2OID

BulkCopyTempM3ToM3_0

ImportTemp_M3_01

M3_RIP及M3_RIP_PDF

Global_MaxM3OID

之前避免出现占用同一个OID的方案为:

以M1为例:

Begin Transaction

  1. 查询出当前当前Global_MaxM1OID中MaxOID的值,存储为@MaxOID;
  2. Set @MaxOID=@MaxOID+@TempCount;
  3. 修改Global_MaxM1OID中的MaxOID值       

Commit

但这里是出现问题的:

  1. 查询出当前当前Global_MaxM1OID中MaxOID的值,存储为@MaxOID;

该语句出现在Begin Transaction的第一行就不能保证会锁定表Global_MaxOID;

修改方案:

添加新列:Flag int到表Global_MaxM1OID中,

事务语句块改写为:

Set XACT_ABORT ON;
Begin Transaction
         ----- 确保一进入事务语句块就锁表(TN.Global_MaxM1OID,TN.Global_MaxM1_M2OID),防止其他存储过程实例再次操作这些表,直到该语句块结束为止
         Update TN.Global_MaxM1OID Set Flag=1 Where OID=1;
         Update TN.Global_MaxM1_M2OID Set Flag=1 Where OID=1;
 
         Select @MAXM1OID =MaxOID From TN.Global_MaxM1OID Where oid=1;
         Select @MAXM1_M2OID =MaxOID From TN.Global_MaxM1_M2OID Where oid=1;
 
         Update TN.Global_MaxM1OID SET MaxOID=(@MaxM1OID+@TempCount), Flag=0 where oid=1;
         Update TN.Global_MaxM1_M2OID SET MaxOID=(@MaxM1_M2OID+@TempCount), Flag=0 where oid=1;
Commit Transaction;

数据不一致调试跟踪方案:

当我们导入数据时发现数据导入的数据量很小很显然是导入的数据很多没有入库,DBA采用日志表TN.Logger跟踪的方案;

  1. TN.Logger表中字段的意义:

Logger字段

字段值意义

OID

编号,自增列,非主键

ENodeBID

当前操作的基站编号ENODEBID

ProcedureName

当前记录写在哪一个存储过程中

EntryM3OID

该存储过程占位之前Global_MaxM3OID值

ExportM3OID

该存储过程占位之后Global_MaxM3OID值

EntryM1OID

该存储过程占位之前Global_MaxM1OID值

ExportM1OID

该存储过程占位之后Global_MaxM1OID值

EntryM2OID

该存储过程占位之前Global_MaxM2OID值

ExportM2OID

该存储过程占位之后Global_MaxM2OID值

EntryM1_M2OID

该存储过程占位之前Global_MaxM1_M2OID值

ExportM1_M2OID

该存储过程占位之后Global_MaxM1_M2OID值

ReportTime

该基站MR上报时间

CurrentRowCount

当前临时表操作数据记录数量

OperateDateTime

当前日志记录时间

  1. 在web.config中添加了配置
<AppSettings>

<!—当配置项为true:时,开启日志;false时,关闭日志 -à

<add Key=”IsLogger” Value=”true|false”>
</AppSettings>
  1. 在BulkCopy中添加以下语句块: 

把解析入库的TempM1,TempM2,TempM3不从临时表中删除,以便我们能监控到我们解析了多少数据,我们写入到M1,M2,M3分别有多少记录,从而达到跟踪的效果;

同时还记录了每次线程进入占用的MaxOID值,从而也可以调试到每个线程占用MaxOID的情况.