DM Logmnr是达梦数据库的日志分析工具,包括JNI接口和C接口,DM Logmnr JNI接口由位于DM安装目录的jar文件夹下com.dameng.logmnr.jar包提供,logmnr.jar包括LogmnrDll和LogmnrRecord两个类。LogmnrDll提供日志挖掘分析的所有接口,LogmnrRecord用于存放调用LogmnrDll日志分析后的结果数据(日志分析结果数据保存在LogmnrRecord的成员变量中)。

     在使用 Logmnr 包中的接口之前,需要先开启两个日志相关参数:一是开启归档(设置
INI 参数 ARCH_INI 为 1);二是开启在日志中记录逻辑操作的功能(设置 INI 参数
RLOG_APPEND_LOGIC 为 1、2 或者 3)。

在SYSDBA用户下创建t_testlogmnr表,插入表数据,并测试更新和删除和truncate操作,sql语句如下:

create table t_testlogmnr(id int,name varchar(50));
insert into t_testlogmnr values(1,'杨明');
insert into t_testlogmnr values(2,'达梦');
insert into t_testlogmnr values(3,'测试');
insert into t_testlogmnr values(4,'韩梅梅');
insert into t_testlogmnr values(5,'李四');
insert into t_testlogmnr values(6,'王五');
insert into t_testlogmnr values(7,'Jack');
update t_testlogmnr set id=id+10 where id<10;
delete t_testlogmnr where id in(11,12);
commit;
truncate table t_testlogmnr;

更新归档

alter system ARCHIVE log current;

查看归档,此时查看V$ARCHIVED_LOG视图可获取最新归档日志(序列号最大的为最新归档日志),假设获取的最新归档日志为“F:\dmdbms_190Pack4\data\DAMENG\arch_local\ARCHIVE_LOCAL1_0x5D02A98E[0]_2021-06-24_15-56-09.log”

select sequence# seq, name , to_char(first_time,'yyyy-mm-dd hh24:mi:ss') first_time, to_char(next_time,'yyyy-mm-dd hh24:mi:ss') next_time, first_change# , next_change# from v$archived_log;

LogmnrDll类定义的是静态方法,所有方法都可以直接通过类名方式调用。详细接口参数说明可参考《DM8程序员手册》。

 接口调用步骤讲解DM LOGMNR JNI接口的使用方法。

函数原型

功能说明

参数说明

返回值

int LogmnrDll.initLogmnr();

初始化 LOGMNR 环境。

无。

0:初始化成功;

< 0 的值和异常:初始化失败。

long LogmnrDll.createConnect(String hostName, int port, String userName, String password);

创建一个分析日志的连接。

hostName:ip 或主库名。

port:端口号。

userName:用户名。

password:密码。

创建的数据库连接标识 ID

int LogmnrDll.addLogFile(long connId, String logFileName, int option);

添加需要分析的归档日志文件。

connId:数据库连接标识 ID。

logFileName:需要分析的归档日志文件名(绝对路径)。

option:可选配置参数。包括以下值:

1:结束当前日志挖掘(隐式调用 endLogmnr,以前添加的归档日志文件将被清除),

并增加新的归档日志文件。

2:删除日志文件。

3:增加的归档日志文件名。

0:添加成功;

< 0 的值和异常:添加失败。注意事项

如果当前已经 startLogmnr,则 addLogFile 将报错,如果需要添加新的日志文件,需要

先调用 endLogmnr 结束当前日志分析后再添加文件。

int LogmnrDll.removeLogFile(long connId, String logFileName);

移除指定的归档日志文件。

connId:数据库连接标识 ID。

logFileName:需要移除档日志文件名(绝对路径)。

0:移除成功;

< 0 的值和异常:移除失败。同 addLogFile 一样,如果当前已经 startLogmnr,则 removeLogFile 将报错,如果需要移

除日志文件,需要先调用 endLogmnr 结束当前日志分析后再移除文件。

int LogmnrDll.startLogmnr(long connId, long trxid, String startTime, String endTime);

启动当前会话的归档日志文件分析,对添加的归档日志文件进行日志分析。

connId:数据库连接标识 ID。

trxid:分析归档日志的事务 id 号,默认为-1,表示不区分事务号。

startTime:分析归档日志的起始时间,默认 1988/1/1。

endTime:分析归档日志的结束时间,默认 2110/12/31。

0:启动成功;

< 0 的值和异常:启动失败。

LogmnrRecord[]LogmnrDll.getData(long connId, int rownum);

获取日志文件分析结果数据。

connId:数据库连接标识 ID。

rownum:获取行数。

获取的 logmnr 记录,为LogmnrRecord 对象数组

int LogmnrDll.endLogmnr(long connId, int option);

终止当前会话的归档日志文件分析。

connId:数据库连接标识 ID。

options:可选模式如下:

0:清除当前会话的归档日志文件分析环境,再次分析时需要重新 add_logfile。

1:保留当前会话的归档日志文件分析环境,不需要重新 add_logfile。

0:终止成功;

< 0 的值和异常:终止失败。

int LogmnrDll.closeConnect(long connId);

关闭当前连接,清理字典缓存等。

connId:数据库连接标识 ID。

0:关闭成功;

< 0 的值和异常:关闭失败。

boolean LogmnrDll.deinitLogmnr();

销毁 LOGMNR 环境。

无。

0:添加销毁;

< 0 的值和异常:销毁失败。

int LogmnrDll.setAttr(long connId, int attr, int attr_value)

设置属性。 有如下三个属性可以配置:

LogmnrDll.LOGMNR_ATTR_PARALLEL_NUM  并行线程数 有效值(2, 16);

LogmnrDll.LOGMNR_ATTR_BUFFER_NUM 任务缓存节点数 有效值(8, 1024);

LogmnrDll.LOGMNR_ATTR_CONTENT_NUM  结果缓存节点数 有效值(256,

2048)。

connId:数据库连接标识 ID。

attr:属性名。

attr_value:属性值。

0:添加成功;

< 0 的值和异常:添加失败。

LogmnrRecord 对象支持的成员变量如下表所示。获取和设置这些变量可以使用相应的
“get+成员变量”和“set+成员变量”方法。 

成员

变量

 类型  说明

scn  

long

当前记录的 LSN

startScn

long

当前事务的起始 LSN

commitScn  

long

 当前事务的截止 LSN

timestamp

String  

当前记录的创建时间

startTimestamp

String  

当前事务的起始时间

commitTimestamp

String

 当前事务的截止时间

xid

String

当前记录的事务 ID 号

operation

String

操作类型包括 start、insert、update、delete、commit、rollback

等语句

operationCode

String

操作类型。插入操作值为 1,更新操作值为 3,删除操作值为 2,事务起始语句值为 6,提交操作值为7,回滚操作值为 36

rollBack 

int  

当前记录是否被回滚(1 是 0 否)

segOwner  

String  

执行这条语句的用户名

tableName  

String  

操作的表名

rowId  

String  

对应记录的行号

rbasqn  

int  

对应的归档日志文件号

rbablk  

int  

RBASQN 所指日志文件的块号从 0 开始

rbabyte

int  

 RBABLK 所指块号的块内偏移

dataObj  

int  

对象 ID 号

dataObjv  

int  

对象版本号

sqlRedo  

 

String  

当前记录对应的 sql 语句

rsId

Stirng  

记录集 ID

ssn

int

连续 sql 标志。如果 sql 长度超过单个 sql_redo 字段能存储的长度,则 sql 会被截断成多个 sql 片段在结果集中“连续”返回

csf

int

与 SSN 配合。最后一个片段的 csf 值为 0,其余片段的值均为 1。没因超长发生截断的 sql 该字段值均为 0

status

int  

日志状态。默认为 0

在Eclipse界面将com.dameng.logmnr.jar包添加到程序中。在Eclipse工程中,右键工程选择【构建路径】->【配置构建路径】,打开JAVA构建配置页面,在“库(Library)”页签中,点击【添加外部JAR】,选择com.dameng.logmnr.jar包,并选择本地库位置(因Logmnr是JNI接口,运行时需调用达梦动态库dll文件,所以需要配置本地库路径,否则无法正常运行),点击【编辑】,填写达梦数据库(驱动)安装bin目录,依次点击【确定】。如下图所示。

java MDC 会影响性能吗_java MDC 会影响性能吗

在JAVA工程中新建TestLogmnr类,代码中指定需要分析的归档日志文件“F:\dmdbms_190Pack4\data\DAMENG\arch_local\ARCHIVE_LOCAL1_0x5D02A98E[0]_2021-06-24_15-56-09.log”,并将分析的归档日志结果数据输出至文件“F:\dmdbms_190Pack4\result.txt”中,每一行表示一个操作语句,不同属性用“|”分割,换行符为“回车换行”,代码参考如下。

package cn.com.test;

import java.io.File;
import java.io.FileOutputStream;
import com.dameng.logmnr.LogmnrDll;
import com.dameng.logmnr.LogmnrRecord;
public class dbmslog {
public static void main(String[] args) {
try
{
//初始化LOGMNR环境
LogmnrDll.initLogmnr(); 
//创建连接
long connid = LogmnrDll.createConnect("localhost", 5230, "SYSDBA",  "SYSDBA");
//添加归档日志文件
LogmnrDll.addLogFile(connid,"F:\\dmdbms_190Pack4\\data\\DAMENG\\arch_local\\ARCHIVE_LOCAL1_0x5D02A98E[0]_2021-06-24_15-56-09.log",3);
//启动日志分析
LogmnrDll.startLogmnr(connid, -1, null, null); 
//获取数据
LogmnrRecord[] arr = LogmnrDll.getData(connid, 100);
/*    将获取的归档日志信息输出至文件中      */
File file = new File("F:\\dmdbms_190Pack4\\result.txt");
FileOutputStream out = new FileOutputStream(file);
StringBuffer sb = new StringBuffer();
String lineendstr = "\r\n";//定义转换字符
String split = "|";//定义分隔符

//定义表头
sb.append("Xid|Operation|OperationCode|Scn|StartScn|CommitScn|Timestamp"
		+ "|SegOwner|TableName|RowId|Rbasqn|rsId|sqlRedo"+lineendstr);
System.out.println("日志分析结果打印:");
for (int i = 0; i < arr.length; i++) {
//if(arr[i].getTableName().equals("T_TESTLOGMNR")){
	sb.append(arr[i].getXid()+split);
	sb.append(arr[i].getOperationCode()+split);
	sb.append(arr[i].getOperation()+split);
	
	sb.append(arr[i].getScn()+split);
	sb.append(arr[i].getStartScn()+split);
	sb.append(arr[i].getCommitScn()+split);
	
	sb.append(arr[i].getTimestamp()+split);
	sb.append(arr[i].getSegOwner()+split);
	sb.append(arr[i].getTableName()+split);
	sb.append(arr[i].getRowId()+split);
	sb.append(arr[i].getRbasqn()+split);
	sb.append(arr[i].getRsId()+split);
	sb.append(arr[i].getSqlRedo()+lineendstr);
//}
}
System.out.println("结果打印完毕");
out.write(sb.toString().getBytes("GBK"));
out.flush();
out.close();
LogmnrDll.endLogmnr(connid, 0);
LogmnrDll.closeConnect(connid);
LogmnrDll.deinitLogmnr();
}catch (Exception e) {
	e.printStackTrace();
	}
	}
	}

     运行后生成的本地文件如下:

java MDC 会影响性能吗_归档日志_02