Apexsql log最佳实践
APEXSQL LOG 解析sql server 事务日志(整体默认DML)
create by : chaoqun.guo
基本介绍:
该软件工具主要是用来解析DML,通过分析事务日志得出redo和undo的SQL脚本。
【0】构建测试数据库与数据
【0.1】创建test数据库(完整模式)
create database test on primary
(
name='test_data',
filename='d:\MSSQL_FIle\test_data.mdf',
size=10MB,
filegrowth=10MB
)
log on
(
name='test_log',
filename='d:\MSSQL_FIle\test_log.ldf',
size=10MB,
filegrowth=10MB
)
【0.2】创建测试表
--(1) create test1 table , use create table
use test;
create table test1(
id int identity(1,1) primary key,
num1 int,
num2 int,
str1 varchar(100),
str2 varchar(200)
)
insert into test1(num1,num2,str1,str2) values(1,2,'a','b');
insert into test1(num1,num2,str1,str2) values(3,3,'aa','bb'),(4,4,'cc','dd');
--(2) select * into new_table from tablename
use test;
go
;with a as (
select 1 as id1 ,2 as id2
union all
select id1+1,id2+1 from a
where id1<=100
)
select * into test2 from a option(maxrecursion 0)
--(3) insert into exists_table select from tableName
select * into test3 from test1 where 1=2
insert into test3 select num1,num2,str1,str2 from test1;
【1】apexSql log 操作
【1.1】连接数据库
连接数据库,可以解析在线/正在使用的ldf文件,我们这里选择 test 库。这里可以使用windows登录方式和SQL登录方式,我这里是软件和数据库在同一台机器上,就用windows了。
【1.2】添加备份目录/备份文件
此功能可以查看历史备份出来的事务日志内容。
由于sql server 备份事务日志会截断事务日志信息(截断的概念:就是把某个位置之前的所有事务日志信息全都设置为可重用,后续就可以被其他信息覆盖),所以如果要追查的事务日志已经被截断,那么则需要添加上事务日志备份
【1.3】功能选择-- open results in grid
这里以网格结果为演示案例
【1.3.0】open results in grid 在网格中打开所有事务日志记录
注意,设置好过滤条件,否则可能会因为事务日志记录过多加载很久
【1.3.1】Filter setup过滤器设置
(1)Time range过滤器设置
1-》过滤时间范围
2-》Operations 过滤操作行为
这里可以选择增删改以及DDL等。我们这里把create table 也勾上
3-》Tables 表过滤操作
这里可以选择用户表/系统表 等等,这里我们勾上所有用户表
4-》advanced options 高级选项
<transactions>事务过滤
这里可以设置事务的状态以及事务的持续时间筛选
<Users>操作账户过滤
<Field values>值范围过滤
可以选择表/列,值范围筛选
<Server process ID>服务器进程过滤
这里可以添加你要过滤筛选的进程ID
<Transaction descriptions>事务描述过滤
5=》additional options补充选项
<display columns>显示的列名
<Old table ID mappings>老表映射现有表
有时候有改名的情况,所以加上映射操作。
选完之后,直接点击完成。
【1.3.2】结果展示
这样,所有的操作就都出来了。下面的是操作详情
我选中insert行,下面的操作详情界面会出现我具体之前操作的值,对应我们【0.2】中的第1个insert into test1(num1,num2,str1,str2) values(1,2,'a','b') 语句。
我们可以查看它的redo/undo以及相关的行历史/事务信息。
行历史操作记录
Undo脚本
Redo脚本
事务信息
【1.3.3】不同插入方式的记录情况
我们可以从【0.2】得知,我们用了3种插入方式
-
insert into table values
-
create new_table select * from tablename
-
insert into select
我们来看一下他们的区别;
create new_table select * from tablename
很明显,在事务日志记录中上图把语句与插入拆开了,然后insert这个整体 是一个操作语句中包含了100记录。
后面这个insert into select ,很明显在事务日志中所有语句都被拆成了单行记录操作。
【1.3.4】测试增删改操作
--(1)删除 test2表id1<50的行
Use test;
Delete test2 where id1<50;
--(2)更新 test3 表 num1=3的把 num2=num1*11
Use test;
Update test3 set num2=num1*11 where num1=3
--(3)插入操作,在【0.2】中的(1)已经操作过了。
点击一下刷新,最新的信息就出来了。
<update>选中update查看下面的详情
redo
Undo,直接就可以生成脚本还原成之前值,同时也记录了该语句是什么时候执行的
操作详情可以查看,修改的一个前后情况
行列式记录可以查看,改行之前做过哪些草走
<insert>
在[1.3.3]中已经展示过了,这里就不再展示了。
<delete>
Undo
Redo
【1.3.5】持续审计
会有一个跟踪文件,记录当前所有记录和后续跟踪。
刷新之后,就只会显示该面板之后操作的记录情况了。
查看
进行一些操作;
use test;
delete test2 where id1<20;
insert into test2(id1,id2) values(100,100);
delete test2 where id1<60;
点击一下刷新,结果如下,只有最新的操作记录了。并且,由于 delete test2 where id1<20;没有删除任何行,所以事务日志里并没有记录
【1.4】批量恢复
【1.4.1】选择生成undo/redo脚本
我们可以勾上我们想要生成对应undo/redo的记录操作,然后点击对应的redo/undo按钮即可
这里我随便选2条记录生成undo脚本
然后脚本就出来了。
【1.4.2】根据事务ID生成undo/redo脚本
如果说,并发很多或者行数太多,我们手电操作恢复比较困难。一个是行数比较多,另外一个是行与行之间会有各种正常不正常的操作。
比如,我们这里的误操作是
Delete test2 where id1<50;
但实际运行的时候可能中间还夹杂了很多 insert/update以及其他行的delete
我们只想要这个事务语句操作的undo脚本。
(1)我们可以看到误操作的事务信息
(2)选中该事务的其中一行,点击上方的select transaction
-
然后全部选中
(4)生成undo
看到这个脚本的上方按钮了吗?我们可以直接在这个工具里点击 execute 运行这个undo脚本,相当于远程连接执行SQL。
【1.5】功能选择—undo/redo
过滤器是一样的,这里就不再赘述
、
选择生成redo还是undo脚本,并选择存储位置
完成,下面还有命令行,这里我们可以用cmd 以dos命令来执行
打开文件查看,对照一下,没有问题,的确实从最后的update反向先执行,然后用insert回滚我们的delete,最后用delete回滚我们最开始的insert 数据
【1.6】功能选择—create before-after report
这个,顾名思义,就是创建一个操作前后的对比报告
过滤器,详细描述见见[1.3.1]
只能对时间,和表进行筛选
选择生成的文件类型,根据需求选择类型
结果集:
就是把操作前后的值变化情况一一列举出来。
这里我们看看SQL结果集和HTML结果集;
SQL:会建表,收集操作类型信息和集体值信息
HTML:这里会显示操作类型和每一步操作对应的值信息
【1.7】功能选择—Export results
过滤器详情,见【1.3.1】
结果:和【1.6】一样,只是多了更多的过滤选项
【2】使用批处理脚本 .bat 操作
如何知道脚本怎么写?用界面操作后,保存下来脚本,直接复制到dos界面即可。
执行成功。
【3】解析离线备份文件
【3.1】测试脚本
create database test;
go
use test;
go
select getdate()
create table test1(num1 int,num2 int);
insert into test1 values(1,1)
insert into test1 values(2,1)
insert into test1 values(3,1)
insert into test1 values(4,1)
insert into test1 values(5,1)
insert into test1 values(6,1)
checkpoint
select * from test1
backup database test to disk='D:\backup_bak\test.bak' with init
insert into test1 values(11,11)
insert into test1 values(22,21)
insert into test1 values(33,31)
insert into test1 values(44,41)
insert into test1 values(55,51)
insert into test1 values(66,61)
checkpoint
backup log test to disk='D:\backup_bak\test_1.trn' with init
update test1 set num2=100
checkpoint
backup log test to disk='D:\backup_bak\test_2.trn'with init
delete test1 where num1<3
checkpoint
backup log test to disk='D:\backup_bak\test_3.trn' with init
select * into test2 from test1
insert into test2 values(11,11)
delete test1 where id <5
delete test2 where id<5
backup log test to disk='D:\backup_bak\test_4.trn' with init
【3.2】查看使用
(1)恢复全备到本地起名test
(2)打开软件选择我们刚恢复的test库
(3)把bak和trn都加进来
(4)查看结果
可以看到我们这个是因为是 对 test2表操作,所以未知。因为在我们恢复的全被 test库中,并没有test2表的元数据。
【3.3】数据什么时候能直接读,什么时候需要还原
-
直接利用bak+trn恢复到数据库之后,用apexsql查看
-
直接利用bak恢复到数据库,然后连接选择该数据库,然后添加文件选择bak+你要解析的事务日志文件,可以不连续。
但如果这段事务日志中间有DDL,DDL所在事务日志LSN之后全不可用。
见测试脚本:这里有个 select * into test2 from test1; 在倒数第5行,这是一个新的object_id
后续的对于 delete test2表的操作解析,也失败了,显示的是unknowin