场景:
我们导入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)
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
- 查询出当前当前Global_MaxM1OID中MaxOID的值,存储为@MaxOID;
- Set @MaxOID=@MaxOID+@TempCount;
- 修改Global_MaxM1OID中的MaxOID值
Commit
但这里是出现问题的:
- 查询出当前当前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跟踪的方案;
- 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 |
当前日志记录时间 |
- 在web.config中添加了配置
<AppSettings>
<!—当配置项为true:时,开启日志;false时,关闭日志 -à
<add Key=”IsLogger” Value=”true|false”>
</AppSettings>
- 在BulkCopy中添加以下语句块:
把解析入库的TempM1,TempM2,TempM3不从临时表中删除,以便我们能监控到我们解析了多少数据,我们写入到M1,M2,M3分别有多少记录,从而达到跟踪的效果;
同时还记录了每次线程进入占用的MaxOID值,从而也可以调试到每个线程占用MaxOID的情况.