在使用 DB2 的 Community 版本的 Docker 镜像 ibmcom/db2
进行测试,启动 Docker 容器的命令是
$ docker run -name db2server --privileged=true -p 50000:50000 \
-e LICENSE=accept \
-e DB2INSTANCE=db2user \
-e DB2INST1_PASSWORD=password123 \
-e DBNAME=test \
ibmcom/db2
当使用多线程以及 JDBC 的 Batch Update 时,出现 "The transaction log for the database is full" 问题,一旦出现这个问题时,用数据库客户端连接后即使执行一条简单的 insert/update 语句也会报同样的错误。于是只能减少线程数和 Batch Update 时的记录来勉强过关,但性能上与其他数据库就有很大的差别了。
问题在哪里
因为在产品数据库中用 10 个线程,Batch Size 设置为 500 应该不会过分,所以必须找到 transaction log 限制在哪里。
DB2 的操作需用 db2 命令,在 Docker 容器中要切换到 ${DB2INSTANCE} 环境变量代表的用户,我们这里是 db2user
, 因此我们登陆到 db2server Docker 容器中
$ docker exec -it db2server sh -c "su - db2user"
$ export DBNAME=test
我们进入到 Docker 容器中后就可以执行 db2 命令了,查看 log file 相应的数据库配置
$ db2 get db cfg | grep -i "log file"
Log file size (4KB) (LOGFILSIZ) = 1024
Number of primary log files (LOGPRIMARY) = 16
Number of secondary log files (LOGSECOND) = 22
Changed path to log files (NEWLOGPATH) =
Path to log files = /database/data/db2user/NODE0000/SQL00001/LOGSTREAM0000/
First active log file = S0000000.LOG
Num. of active log files for 1 active UOW(NUM_LOG_SPAN) = 0
Percent log file reclaimed before soft chckpt (SOFTMAX) = 0
这里我们看到日志文件大小(LOGFILESIZ) 为 1024, 其实质就是在目录 Path to log files
下的一个个文件大小不能超过 1K 大小,真的是一个稍微大的事物就容纳不下。
修改日志大小上限
我们要对它的值进行修改,另两个配置 LOGPRIMARY 和 LOGSECOND 必要时也改一改。使用命令
$ db2 update db cfg using LOGFILSIZ 10240
$ db2 update db cfg using LOGPRIMARY 100
$ db2 update db cfg using LOGSECOND 100
改完后可用 db2 get db cfg | grep -i "log file"
立即看到修改后的值,但要生效的话必须重启数据库实例。
重启数据库实例
$ db2 force applications all
$ db2stop force
$ db2start
说明:如果没数据库连接,db2stop 就能停止数据库,否则会提示
QL1025N The database manager was not stopped because databases are still active.
用 db2stop force
强制停掉数据库,先用 db2 force applications all
断掉数据库连接后,其实紧接着的 db2stop
就不需要 force
了
待数据库重新启动后就能支持更大的事物,更多客户端连接及更大的 Batch Update Size 了。
最后总结一下
挑出几个必须的步骤
- 进到数据库服务器并切换到数据库用户
- db2 get db cfg for test | grep LOGFILSIZ 查看日志文件大小限制
- db2 update db cfg for test using LOGFILSIZ 10240
- db2stop force
- db2start
执行 db2 命令时的补充:
db2 update db cfg 命令可带上数据库名称(比如未设置 DBNAME 环境变量的情况下)
$ db2 update db cfg for test using LOGFILSIZ 10240
如果没有设置 DBNAME=test 环境变量就执行 db2 get db cfg
命令会提示
SQL1024N A database connection does not exist. SQLSTATE=08003
不想设置 DBNAME 环境变量操作该数据库的办法可以分两步
- 先执行
db2
进行 db2 的提示符 "db2 =>" - 在 "db2 =>" 提示符下执行 "connect to test"
- 继续在 "db2 =>" 提示符下执行 "get db cfg" 命令
链接: