某日下午,开发报告说在执行DML操作时,数据库报事务日志已满的错误。
db2diag.log数据库日志中的报错信息:
2013-04-01-16.43.30.736907+480 E2147482982C502 LEVEL: Error
PID : 126660 TID : 1 PROC : db2agent (SSO) 0
INSTANCE: db2inst1 NODE : 000 DB : SSO
APPHDL : 0-1103 APPID: GA0429B5.F627.130401082711
FUNCTION: DB2 UDB, data protection, sqlpgResSpace, probe:2860
MESSAGE : ADM1823E The active log is full and is held by application handle
"1103". Terminate this application by COMMIT, ROLLBACK or FORCE
APPLICATION.
客户端具体信息如下:
$db2 delete from tzsdb01
DB21034E 该命令被当作 SQL 语句来处理,因为它不是有效的“命令行处理器”命令。
在 SQL 处理期间,它返回:
SQL0964C 数据库的事务日志已满。 SQLSTATE=57011
这个问题的原因是:表中数据量过大,delete 时,会写入日志,但日志容量过小。
解决方法: 增大日志容量、数据量 或 减少一次的删除数据量,分多次删除。
生产环境为避免白天停库,提示开发分多次删除,这样就不出错了。但是要彻底解决这个问题,还需申请停库修改数据库参数。
我们先看一下,数据库的关于日志的配置参数
$ db2 get db cfg for tzsdb01
Database Configuration for Database zssqdb01
Database configuration release level = 0x0d00
Database release level = 0x0d00
Database territory = cn
Database code page = 1208
Database code set = UTF-8
Database country/region code = 86
Database collating sequence = IDENTITY
Multi-page file allocation enabled = YES
Log retain for recovery status = RECOVERY
User exit for logging status = YES
Self tuning memory (SELF_TUNING_MEM) = ON
Size of database shared memory (4KB) (DATABASE_MEMORY) = AUTOMATIC(1662183)
Database memory threshold (DB_MEM_THRESH) = 10
Max storage for lock list (4KB) (LOCKLIST) = AUTOMATIC(130720)
Percent. of lock lists per application (MAXLOCKS) = AUTOMATIC(97)
Package cache size (4KB) (PCKCACHESZ) = AUTOMATIC(421273)
Sort heap thres for shared sorts (4KB) (SHEAPTHRES_SHR) = AUTOMATIC(46809)
Sort list heap (4KB) (SORTHEAP) = AUTOMATIC(9361)
Database heap (4KB) (DBHEAP) = AUTOMATIC(2626)
Catalog cache size (4KB) (CATALOGCACHE_SZ) = 300
Log buffer size (4KB) (LOGBUFSZ) = 4096
Log file size (4KB) (LOGFILSIZ) = 1024
Number of primary log files (LOGPRIMARY) = 10
Number of secondary log files (LOGSECOND) = 4
Changed path to log files (NEWLOGPATH) =
Path to log files = /home/db2inst1/db2inst1/NODE0000/SQL00001/SQLOGDIR/
先看增大日志的容量,注意红色的值为1024
$db2 update db cfg for zssqdb01 using logfilsiz 8192 将其增大到8192
然后停止应用,停库再启库就生效了
$db2 force applications all
$db2stop
$db2start
如果需要增大日志的数据量则需要进行计算和这样设置,这时日志容量已变为8192
Log file size (4KB) (LOGFILSIZ) = 8192
Number of primary log files (LOGPRIMARY) = 10
Number of secondary log files (LOGSECOND) = 4
现在的日志数据量为
计算公式如下:
数据库事务日志的数据量大小 = ( LOGPRIMARY + LOGSECOND )* LOGFILSIZ * 4KB
即:
( 10 + 4)* 8192 * 4KB = 458752 K = 458 M (大约数)
下面断开此数据库的所有连接
修改主日志文件个数: db2 update db cfg for <dbname> using LOGPRIMARY 15
修改辅助日志文件个数:db2 update db cfg for <dbname> using LOGSECOND 10
这时的大小=(15+10)*8192*4KB=819200K=819M (大约数)
然后停库再启库,问题得到解决。
注:LOGPRIMARY+LOGSECOND不能超过255,日志空间大小不能超过256G。对于LOGPRIMARY和LOGFILSIZ参数的修改需要断开连接,重连数据库才能生效。LOGSECOND参数的修改则立即生效,对于生产系统比较快的应急解决办法,可以直接先修改此参数。
补充知识:
1,主日志文件的数目 LOGPRIMARY
此数据库配置参数用来指定要预分配的主日志文件个数。主日志文件建立分配给恢复日志文件的固定存储器数量。在循环日志管理模式下,数据库事务将按顺序重复使用主日志,也就是当一个主日志已满时,顺序使用下一个主日志,如果主日志已满,则按需一次分配一个辅助日志,辅助日志在使用完后,将被释放。如果你发现数据库会经常分配辅助日志文件,则可能需要通过增大日志文件大小或增大主日志文件的数目来提高系统性能。
2,辅助日志文件的数目 LOGSECOND
此数据库配置参数用来指定按需分配的辅助日志文件个数。尽量不要把此参数的值设置成“ -1 ” ,“ -1 ”代表你在请求一个无限的活动日志空间,数据库也不会报数据库事务日志已满错误,如果空间不足则会报日志磁盘已满错误。
3,日志文件大小 LOGFILSIZ
此数据库配置参数用来指定日志文件的大小。
4,数据库事务日志已满错误
数据库事务日志已满错误是指当前事务无法写入到活动日志中(此时主日志文件和辅助日志文件已经全部用完或者没有足够当前事务写入的空间),需要注意的是,这个错误和日志磁盘空间已满是两个概念。数据库事务日志已满不是由于磁盘空间满引起的,而是由于没有落实的事务总体过大,超过了数据库事务日志所能容纳的最大大小所造成的。
当出现这样的错误时,不要尝试使用 DB2STOP FORCE 命令来强制停掉数据库,建议大家使用 FORCE APPLICATION 命令停掉引起这个错误的应用程序或者停掉所有的应用程序。也不建议大家使用 KILL 命令来杀掉任何 DB2 相关的进程。如果 使用DB2STOP FORCE命令hang住了,最后再尝试杀掉进程,重新DB2START或重启服务器。