guanwei
作者guanwei·2016-02-21 22:03
助理咨询顾问·ETC

数据文件误删除的解决办法

字数 10176阅读 1595评论 2赞 3

中秋刚过,我给论坛上的各位苦B青年拜个晚年!祝大家元宵节快乐!今天要侃的是环境是Linux平台上的DB2,主题是数据文件误删除的解决办法。如果DB2正在运行,我们在操作系统级别不小心(或被坏人别有用心)把数据文件给RM掉会是一个什么情况?数据库会不会瞬间崩塌?不知道您是否看过拙作《Page的更新过程》,要回答这个问题,先想一下文中说的页清除程序写数据文件的条件,根据那几个条件,预计DB2不会立即完蛋,现在让我们来实验一下。

以V95为例,创建一个数据库zuma,再创建一个AS类型的表空间TS,在这个表空间里建一个表T,只有一列A是int型,写一些数据进去,然后把TS对应的文件容器干掉:

db2inst1@db2v95:~/db2inst1/NODE0000/ZUMA/T0000003>l

total 32780

drwx--x--x 2 db2inst1db2iadm1     4096 Feb 21 19:19 ./

drwx--x--x 6 db2inst1db2iadm1     4096 Feb 21 19:23 ../

-rw------- 1 db2inst1db2iadm1 33554432 Feb 21 19:25 C0000000.LRG

-rw------- 1 db2inst1db2iadm1        0 Feb 21 19:19.SQLCRT.FLG

db2inst1@db2v95:~/db2inst1/NODE0000/ZUMA/T0000003>rm C0000000.LRG

此时DB2没有任何不良反应,甚至db2diag.log也不报任何错,执行和T有关的操作也都OK。

db2inst1@db2v95:~/db2inst1/NODE0000/ZUMA/T0000003>db2 "insert into t select * from t fetch first 100 rows only"

DB20000I  The SQL command completed successfully.

如果这个时候关闭实例,那么数据库再次激活时,用脚想都知道这个表空间会OFF LINE,要想恢复这个故障,非利用备份恢复不可,或通过非常规手段进行磁盘扫描,掘地三尺把数据文件恢复回来。假如实例没有关闭,遇到这样的情况,则可以很轻松恢复,所用原理是实例启动后,db2sysc进程会打开所有DB2需要用到的文件,即db2sysc持有打开文件的句柄,即使磁盘文件不在,对应文件也可以读写。

db2inst1@db2v95:~/db2inst1/NODE0000/ZUMA/T0000003>ps -ef|grep -i db2sysc

db2inst1  7836 7834  0 19:14 pts/0    00:00:20 db2sysc 0                                     

db2inst1  8496 7643  0 20:00 pts/0    00:00:00 grep --color=auto -i db2sysc

进程号是7836,cd/proc/7836/fd,列出目录,可以看到Linux已经把这个文件标记为删除:

lrwx------ 1 db2inst1db2iadm1 64 Feb 21 20:01 24 ->/home/db2inst1/db2inst1/NODE0000/ZUMA/T0000003/C0000000.LRG (deleted)

现在把它拷贝回原来的位置就好了。

db2inst1@db2v95:/proc/7836/fd>cp 24 /home/db2inst1/db2inst1/NODE0000/ZUMA/T0000003/C0000000.LRG

db2inst1@db2v95:/proc/7836/fd>cd /home/db2inst1/db2inst1/NODE0000/ZUMA/T0000003/

db2inst1@db2v95:~/db2inst1/NODE0000/ZUMA/T0000003>l

total 32776

drwx--x--x 2 db2inst1db2iadm1     4096 Feb 21 20:02 ./

drwx--x--x 6 db2inst1db2iadm1     4096 Feb 21 19:23 ../

-rw------- 1 db2inst1db2iadm1 33554432 Feb 21 20:02 C0000000.LRG

-rw------- 1 db2inst1db2iadm1        0 Feb 21 19:19.SQLCRT.FLG

现在再看DB2,和没发生什么事儿似的,继续工作,可以正常关闭和再次激活:

db2inst1@db2v95:~/db2inst1/NODE0000/ZUMA/T0000003>db2 connect reset

DB20000I  The SQL command completed successfully.

db2inst1@db2v95:~/db2inst1/NODE0000/ZUMA/T0000003>db2 activate db zuma

DB20000I  The ACTIVATE DATABASE command completedsuccessfully.

这个例子告诉我们,别动不动就用重启的办法解决问题,有时胡乱重启会坏菜的!这个案例的恢复实验至此完成,但思考并不应该结束,因为如果长时间不恢复文件,内存总有满的时候,DB2迟早要写文件,如果数据文件此时不在,会发生什么?刚才说过,DB2仍然可以正常读写,那么是不是DB2在写文件而又找不到文件时,会一声哀嚎,在db2diag.log中留下痕迹,然后继续干活?关键是这个哀嚎的时机,是不是在我们掌握之中?来继续实验。

这个实验的思路是这样的,我们从CHNGPGS_THRESH参数下手,把它设置成最小的5%,这样只要缓冲池肮脏率达到5%,理论上就会发生写磁盘操作,为了不让SOFTMAX干扰触发写操作,我把SOFTMAX设成1000,嘿嘿!

db2inst1@db2v95:~> db2 create db zuma

DB20000I  The CREATE DATABASE command completed successfully.

 db2inst1@db2v95:~> db2 activate db zuma

DB20000I  The ACTIVATE DATABASE command completed successfully.

db2inst1@db2v95:~> db2 connect to zuma

 

   Database Connection Information

 

 Database server         = DB2/LINUXX8664 9.5.8

 SQL authorization ID   = DB2INST1

 Local database alias   = ZUMA

 

db2inst1@db2v95:~> db2 create bufferpool bp size 100 pagesize 4096

DB20000I  The SQL command completed successfully.

db2inst1@db2v95:~> db2 create tablespace ts bufferpool bp

DB20000I  The SQL command completed successfully.

db2inst1@db2v95:~> db2"create table t (a int) in ts"

DB20000I  The SQL command completed successfully.

db2inst1@db2v95:~> db2 get db cfg for zuma |grep -i softmax

 Percent log file reclaimed before soft chckpt(SOFTMAX) = 520

db2inst1@db2v95:~> db2update db cfg for zuma using softmax 1000

DB20000I  The UPDATE DATABASE CONFIGURATION commandcompleted successfully.

SQL1363W  One or more of the parameters submitted forimmediate modification were not changed dynamically. For these configurationparameters, all applications must disconnect from this database before thechanges become effective.

 db2inst1@db2v95:~> db2 getdb cfg for zuma |grep -i chngpgs

 Changed pages threshold                (CHNGPGS_THRESH) = 80

 db2inst1@db2v95:~> db2update db cfg for zuma using chngpgs_thresh 5

DB20000I  The UPDATE DATABASE CONFIGURATION commandcompleted successfully.

SQL1363W  One or more of the parameters submitted forimmediate modification were not changed dynamically. For these configurationparameters, all applications must disconnect from this database before the changesbecome effective.

 db2inst1@db2v95:~> db2 terminate

DB20000I  The TERMINATE command completed successfully.

db2inst1@db2v95:~> db2 deactivate db zuma

DB20000I  The DEACTIVATE DATABASE command completedsuccessfully.

db2inst1@db2v95:~> db2 activate db zuma

DB20000I  The ACTIVATE DATABASE command completedsuccessfully.

准备工作做好了,来看一下现在bp的dirty情况,显然啥也没有:

db2inst1@db2v95:~> db2pd-d zuma -dir bp=2

 Database Partition 0 --Database ZUMA -- Active -- Up 0 days 00:00:39 -- Date 02/21/2016 19:24:20

Bufferpool: 2        

   Dirty pages %       : 0 / 100 (0.00% dirty)

 Recovery information:

   lowtranlsn              : 000000000178800C

   minbuflsn               : FFFFFFFFFFFFFFFF

   nextlsn                   : 000000000178800C

   LFH lowtranlsn       : 000000000178800C

   LFH minbuflsn         : 000000000178800C

   LFH nextlsn             : 000000000178800C

   Active Log bytes in use   : 0

   Current Softmax         : 41943040

有2个地方比较有意思,值得一想,一个是minbuflsn,全是F,后面只要有交易产生,它就不再是全F了,为什么开始是全F?DB2的原理大家加油猜!另一个是Current Softmax,这个41943040是啥意思?还记着我们刚才把softmax设置成1000吗?1000是百分之1000的意思,1000除以100等于10,10个log是多大?

db2inst1@db2v95:~/db2inst1/NODE0000/ZUMA/T0000003>db2 get db cfg for zuma|grep -i logfil

 Log file size (4KB)                         (LOGFILSIZ) = 1024

4K乘以1024,再乘以10,刚好是41943040哦。好了,这些目前都不是关注重点,我们再造些数据,然后看db2pd -d zuma -dir bp=2的结果。

db2inst1@db2v95:~> db2pd-d zuma -dir bp=2

 Database Partition 0 --Database ZUMA -- Active -- Up 0 days 00:04:10 -- Date 02/21/2016 19:27:51

 Bufferpool: 2        

   Dirty pages %       : 1 / 100 (1.00% dirty)

   Bufferpool minbuflsn: 000000000178805D

 Oldest page info:

DirtyLst   TspID PPNum      ObjID OPNum      Typ UFlag fixcount   wgt CPC LSN              pgLtch

n/a        3    128        4     0         0   3     0         1   0   000000000178805D 0x00007F72AA32B518

   Dirty pages:

DirtyLst   TspID PPNum      ObjID OPNum      Typ UFlag fixcount   wgt CPC LSN              pgLtch

2          3    128        4     0         0   3     0         1   0   000000000178805D 0x00007F72AA32B518 hX:0sH:0 xW:0 rC:0

 Recovery information:

   lowtranlsn              : 00000000017880AE

   minbuflsn               : 000000000178805D

   nextlsn                  : 00000000017880AE

   LFH lowtranlsn         : 00000000017880AE

   LFH minbuflsn          : 000000000178805D

   LFH nextlsn             : 000000000178800C

   Active Log bytes in use    : 81

   Current Softmax         : 41943040

现在Dirtypages的百分比是1,最下面的minbuflsn已经有值,LFH有三个值,还记得日志控制文件叫什么名字吗?SQLOGCTL.LFH.1和SQLOGCTL.LFH.2对吧?结合db2pd的log的CurrentLSN来看,你会看到日志LSN这内存中这些LSN的关系。中间有2段内容,一个是Oldest page info,另一部分是Dirty pages的List,一会再写数据,BP越脏这个List内容就会越来越多。TspID含义一目了然,PPNum也容易知道,相当于Page的ID,pgLtch是典型的IBM不写元音字母的命名风格,是Page Latch,啥意思?其实就是这页在内存中的地址呗,再看一下db2pd的log,这里边有一个Address,这些地址离的近吧?但不可能是一样的,各占各的地盘。把这些Address或Latch经常做做减法,是等差数列时,就必有讲究在里面,哈哈!

现在我们赶快删除TS表空间的数据文件,然后在另一个窗口里归档db2diag.log,touch一个新的后用tail-f db2diag.log把它监控起来。

现在继续insert into t吧,把dirty page百分比搞到5%。

Bufferpool: 2        

   Dirty pages %       : 5 / 100 (5.00% dirty)

   Bufferpool minbuflsn: 000000000178805D

db2diag.log没有反应!继续做,难道是要超过5%才有作用?实验证明,也不是哦!OK,本实验后续的分析到此结束,旨在抛砖引玉,现在想说的是,关于CHNGPGS_THRESH,别理会信息中心说了什么,只相信你亲眼看到的好了。

我的db2diag.log有反应是在DB2需要写SMP时,哎呀,今天太晚了,老婆催着让去给打洗脚水呢,以后再继续去想,再见再见!

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

3

添加新评论2 条评论

zbliuyuzbliuyu系统工程师齐商银行
2016-02-25 14:57
学习了!~~
cwhcwh数据库管理员cwh
2016-02-25 13:12
感謝,剛好遇到這個問題
Ctrl+Enter 发表

作者其他文章

  • RR隔离级别下的行锁分析
    评论 0 · 赞 2
  • 工作负载概念
    评论 6 · 赞 3
  • DB2的SMP和EMP
    评论 2 · 赞 1
  • 多温度存储(扫盲帖)
    评论 0 · 赞 0
  • Page的更新过程
    评论 2 · 赞 1
  • 相关文章

    相关问题

    相关资料

    X社区推广