1 问题描述
某客户达梦主备集群系统主库反馈用客户端连接不上,通过检查数据库日志发现如下图报错:
从报错,可以发现无法创建新的归档日志文件,导致数据库挂起了。
2 问题处理
首先检查操作系统磁盘是否不足,通过d f - h 查询,发现数据文件磁盘已经100 % 的使用率。对方技术人员反馈前两天还有1 T 的可用空间,怎么突然就没有了空间?通过查询数据文件大小,发现T EMP.DBF 的大小超级大,占1.7 T 的大小。
可以锁定,就是临时文件不断扩展导致磁盘空间不足影响到数据库。所以,要解决此次故障,正常思路是需要缩小临时表空间的大小,腾出空间,使数据库恢复正常。那么怎么缩小临时表空间的大小呢,目前数据库是无法登陆的?
首先,达梦对应临时表空间是可以用参数控制的,d m.ini 里面 TEMP_SIZE 和 TEMP_SPACE_LIMIT 参数。
我将TEMP_SIZE 设置为 1000 (生产建议设置这个值), TEMP_SPACE_LIMIT 设置为 500000 。重启数据库服务,发现重启不了,原因还是空间不足。
再次检查数据盘是否有地方腾出空间。发现归档文件占用比较大有近1.5 T ,且保存了时间比较长的归档日志,通过和对方技术人员沟通,确认可以删除整个3 月份的归档日志(因为他们有备份归档日志)。
删除一定量的归档日志后,操作系统有几百G 可用空间,再次重启数据库服务。但是没有那么顺利,数据库服务迟迟停不下来。使用 t op 命令查看进程,发现有好多个d isql 在运行,通过k ill 命令杀掉这些进程。数据库重启成功,通过查看数据库日志,最终数据库恢复正常。通过查看监视器,主备集群恢复。
最后,查看T EMP.DBF 的大小,发现T EMP.DBF 开始减小,由1.7 T 减小到了1 T ,应该还会再减小,直到设置的TEMP_SIZE 。
3 问题思考
3.1 临时表空间的作用是什么,为什么能扩那么大?
临时表空间主要用来做查询和存放一些缓冲区数据。临时表空间消耗的主要原因是需要对查询的中间结果进行排序。重启数据库可以释放临时表空间,如果不能重启实例,而一直保持问题sql 语句的执行, temp 表空间会一直增长。
对于临时表空间,DM 数据库会自动释放在执行 SQL 过程中产生的临时段,并将属于此临时段的簇空间还给临时表空间。需要注意的是, 临时表空间文件在磁盘所占大小并不会因此而缩减 ,用户可以通过系统函数 SF_RESET_TEMP_TS 来进行磁盘空间的清理。
3.2 达梦临时表空间还有什么方法可以缩小空间?
如上所述,当临时表空间扩展的太大时,可以使用达梦的存储过程 SP_TRUNC_TS_FILE 来进行空间的收缩,其定义如下:
SP_TRUNC_TS_FILE (
ts_id int,
file_id int,
to_size int
)
功能说明:
将临时表空间文件截断到指定的大小,仅能截断文件空闲未使用的部分,如果在指定 to_size 后存在已使用数据页,则实际截断大小会大于 to_size 。
参数说明:
ts_id :指定截断文件的临时表空间 ID
file_id :指定截断文件的文件 ID
to_size :指定将文件截断至多大,以 M 为单位; to_size 大小换算成页数后,值必须在 4096 到 2G 之间
返回值:无
举例说明:
将临时表空间文件号为 0 的文件截断到 2048M 大小,库的页大小为 8K 。
CALL SP_TRUNC_TS_FILE (3, 0, 2048);
3.3 达梦临时表空间能否新增?
我们知道,o racle 数据库是可以创建新的临时表空间的。其创建示例如下:
create temporary tablespace TEMP1 TEMPFILE '/oradata/TEMP1_01.dbf' size 100M;
alter database default temporary tablespace TEMP1;
但是达梦是否也可以呢?答案是不能,操作如下:
create tablespace "TEMP2" datafile 'TEMP2.DBF' size 128 autoextend on CACHE = RECYCLE;
3.4 如果数据盘没有空间可以腾出来,该怎么做才能恢复数据库服务?
假设数据盘已经没有可以清理的数据,腾不出空间,并且也不能立马扩展数据盘,那么该怎么处理能够更快的修复数据库?
我的想法是:正常关闭数据库,因为已经数据库已经异常了,连接不上。将一个100 G 以内的数据文件移动到其他有空间的盘。转换d m.ctl 为d mctl.txt ,并编辑d mctl.txt ,修改移动后的这个数据文件的路径,再转为新的d m.ctl 。最后再启动数据库。后面,也可以再把数据文件移动到原来的路径下面。