• 场景:

我们导入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清理日志文件_多线程

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的情况.



基础才是编程人员应该深入研究的问题,比如:

1)List/Set/Map内部组成原理|区别

2)mysql索引存储结构&如何调优/b-tree特点、计算复杂度及影响复杂度的因素。。。

3)JVM运行组成与原理及调优

4)Java类加载器运行原理

5)Java中GC过程原理|使用的回收算法原理

6)Redis中hash一致性实现及与hash其他区别

7)Java多线程、线程池开发、管理Lock与Synchroined区别

8)Spring IOC/AOP 原理;加载过程的。。。

+加关注】。