DB2事务日志使用详解(1)
我们经常接到客户的电话,我的数据库日志满了,有没有什么好办法快速清除?尤其对于一些初入门的DB2使用者去维护一个大数据量的系统,这几乎是他们必然会碰到的一个问题。
我们也经常接到客户更紧急的电话,我的数据库不能使用了,因为日志占用太多空间,文件系统满了,就把日志删除了,现在数据库无法使用,这个是生产系统,需要尽快恢复,有什么办法可以让数据库立刻使用?
碰到这样的问题,我们可以不厌其烦的一遍遍向客户解释这个问题的原因,也可以给出非常明确的解决方案,但是对于很多客户看来,这似乎是一个比较无奈的解决方案,他们只能承担着这种操作带来的系统中断。
因此,对于数据库的设计人员,开发人员和维护人员来讲,非常清楚的了解数据库的日志原理与合理的规划一些操作以避免发生这样的情况是非常重要的!下面,我们就对数据库的日志原理和使用中经常遇到的问题以及其解决方法跟大家分享下。
1、DB2数据库的日志原理
事务日志记录数据库中所有对象和数据的改变,在早前版本中最大可达256G,其大小为( logprimary + logsecond ) * logfilsiz,其中logprimary + logsecond的值小于或等于256,logfilsiz的最大为262144,在9.5版本中,日志最大已经可以达到512G,其中logfilsz的大小更改为524286。
DB2数据库的日志分为主日志和辅助日志,其中主日志在第一个连接到达数据库或者数据库被激活后立即分配,而辅助日志在主日志大小不够的时候动态分配。所以需要注意一点,日志所在的文件系统的大小必须大于主日志文件与辅助日志文件的大小之和。
DB2数据库有2种日志配置方式,循环日志与归档日志。
循环日志:这是数据库默认的日志使用方式,主日志用来记录所有的更改,当事务提交后,日志文件会被重用。当主日志文件达到限制时,辅助日志文件将被使用。这种日志方式可以进行崩溃恢复和版本恢复,不能进行前滚恢复,不支持在线备份。
当活动事务的使用空间超过主日志和辅助日志的限制或者日志空间超过磁盘可使用空间,将会得到日志满的错误。
归档日志:启用logarchmetd1、logarchmetd2或打开logretain参数,注意,在9.5版本中,不推荐使用logretain参数,其所有的设置值将被忽略。在数据库归档日志规划时,建议不再使用logretain的方法。日志文件将不会被删除-保持在线或者离线状态。支持前滚恢复和在线备份。
疑问:归档日志下,日志一直保留,持续生成新日志,为什么还会出现日志满的错误?
归档日志下,其可用的活动日志大小依然受到主日志与辅助日志大小之和的限制,所以,即使在归档日志下,日志满的场景与活动日志下是完全一样的。
2、日志使用中的问题与解决方法
在日常使用中,我们遇到最多的问题就是日志满,现在用几个实际的例子来看如何分析和解决日志满的问题,一般的,日志满可以分以下几个场景:
A、环境准备,并介绍数据库日志使用大小评估方法:
数据库参数设置如下:
日志文件大小(4KB) (LOGFILSIZ) = 10000
主日志文件的数目 (LOGPRIMARY) = 3
辅助日志文件的数目 (LOGSECOND) = 2
日志总大小为200M.
创建测试用表:
C:\Documents and Settings\administrator>db2 "create table test_log(col int, col2 char(10) ,col3 timestamp,col4 varchar(100),col5 varchar(100),col6 varchar(100),col7 varch ar(100),col8 varchar(100))" |
DB20000I SQL命令成功完成。
创建插入数据的存储过程:
C:\Documents and Settings\administrator>db2 -td@ -vf proc_testlog.sql create procedure proc_testlog(v1 int) begin declare time int default 0; while (time < v1) do insert into test_log values(1,'testlog',current timestamp,'testlogtestlogte……'); set time = time + 1; end while; end |
DB20000I SQL命令成功完成。
我们来评估下插入使用日志的情况,以便构造日志满的场景,使用db2pd来查看事务日志的使用。
分别打开2个db2cmd会话窗口,在窗口1中我们执行:
C:\Documents and Settings\administrator>db2 +c call proc_testlog(1)
返回状态 = 0
会话2中执行:
C:\Documents and Settings\administrator>db2pd -db sample -transactions Database Partition 0 -- Database SAMPLE -- Active -- Up 0 days 00:29:20 Transactions: Address AppHandl [nod-index] TranHdl Locks State Tflag Tflag2 Firstlsn Lastlsn LogSpace SpaceReserved TID AxRegCnt GXID 0x7FC21A80 7 [000-00007] 2 7 WRITE 0x00000000 0x00000 000 0x000027718800 0x000027718800 110 700 0x000000004F13 1 0 |
可以看到这个写操作占用的日志大约为700个字节,在回话1中再重复执行上面的命令,会话2中在看db2pd的输出:
C:\Documents and Settings\administrator>db2pd -db sample -transactions Database Partition 0 -- Database SAMPLE -- Active -- Up 0 days 00:45:55 Transactions: Address AppHandl [nod-index] TranHdl Locks State Tflag Tflag2 Firstlsn Lastlsn LogSpace SpaceReserved TID AxRegCnt GXID 0x7FC21A80 7 [000-00007] 2 8 WRITE 0x00000000 0x00000 000 0x000028E385B8 0x000028E38806 154 1334 0x000000004F57 1 0 |
1334-700=634,我们可以这样评估,单个事务每执行一次表插入,插入一行占用的日志约为700字节,在一个事务中,插入多条记录,插入一行记录占用的日志约为634字节,当然,实际上当插入多行时,日志的大小会比计算值略大。
使用这个方法可以根据业务运行情况来评估需要数据库应该配置的日志大小,也可以评估单个大事务需要的日志空间。
根据估算,200M总日志大小,200*1024*1024/635=330781。因此可以一次插入大约33W记录来构造日志满的场景。