注册
达梦8故障分析方法
培训园地/ 文章详情 /

达梦8故障分析方法

施嘉伟 2025/05/27 68 0 0

第一部分 SQL类故障

SQL类故障主要分为三种类型:结果集异常、执行长时间没有返回数据、以及执行过程中数据库进程异常 。

1.1 结果集异常

首先,需要定位导致结果集异常的SQL语句,这可以通过应用日志、驱动日志、数据库SQL日志或V$SQL_HISTORY视图来实现 。结果集异常通常是由于优化器对查询语句的错误改写或优化造成的 。为了准确复现问题,应确保提取的语句与实际执行的语句、绑定参数以及数据库参数完全一致 。

如果问题可以复现,可以尝试对异常的查询语句进行裁剪,或参照当前执行计划,有目的地通过修改SQL语句来移除计划中的某些操作符,逐步定位导致结果出错的最简语句 。解决方法包括修改参数、使用HINT或改写语句,将有问题的操作符调整为等价的其他操作符 。

查看v$sql_history视图

开启数据库监控参数(默认为开启状态) 。

alter system set 'ENABLE_MONITOR'=1;

执行相关问题模块后,通过SQL_ID, SESS_ID, TRX_ID, TOP_SQL_TEXT, START_TIME等字段在v$sql_history中定位语句 。

select SQL_ID, SESS_ID, TRX_ID, TOP_SQL_TEXT, START_TIME from v$sql_history;

其他可能导致结果集异常的原因 :

查询涉及的全文索引未及时更新 。
查询涉及的物化视图未更新 。
错误地使用确定性函数标记了不确定函数 。
在非一致性读的备机上查询,存在数据延迟 。

1.2 执行长时间没有返回数据

SQL执行长时间无返回可能由以下原因造成:语句本身存在性能问题、执行过程中发生资源等待,或其他特殊情况 。

1.2.1 性能问题

首先通过v$sessions视图确认语句是否处于活动状态,然后利用其trx_id在v$trxwait视图中查询是否存在等待 。若语句处于活动状态且没有等待,则很可能是性能问题,需要进行SQL调优 。

查询活动会话 :

SELECT sess_id, sql_text, user_name, trx_id, state, clnt_ip 
FROM v$sessions 
WHERE state='ACTIVE' AND dbms_lob.substr(sf_get_session_sql(sess_id)) LIKE '%语句片段%';

根据trx_id查询等待状态 :

SELECT * FROM v$trxwait WHERE id = 上面SQL获取到的trx_id;

1.2.2 发生等待

如果语句处于活动状态,并且在v$trxwait中有记录,说明发生了等待 。可以通过WAIT_FOR_ID字段在v$sessions中定位阻塞源头的会话信息 。通常,这是由于某些会话忘记提交或回滚事务,导致其他事务因依赖关系而等待 。在确认安全的情况下,可以关闭客户端、CLOSE会话或发送提交/回滚命令来解决 。

另一种等待不会在V$TRXWAIT中显示,例如,当某表在进行DDL操作时,其他会话尝试查询该表会发生字典对象等待 。这种阻塞可以通过查询V$LOCK来确认 。

SELECT * FROM v$lock WHERE blocked = 1;

DDL操作导致的等待时间由dm.ini参数DDL_WAIT_TIME控制(默认为10秒),超时会抛出锁超时错误 。

1.2.3 特殊情况

其他可能导致等待的情况包括 :

临时表空间不足:查询中使用了临时表、排序、哈希连接等操作,但dm.ini中配置的临时表空间大小受限,且未被及时释放 。
主备环境延迟:在主备或读写分离环境中,由于备机IO异常、网络问题或数据延迟达到阈值,导致主机上需要刷REDO日志的语句发生等待 。
大表删除后的性能问题:对大表进行大量DELETE或TRUNCATE操作后,数据仅被标记为删除,回收站清理这些数据页需要时间,导致后续操作缓慢 。
数据库BUG导致的死锁:数据库内部临界区资源出现死锁,无法自动处理,这通常是最后考虑的可能性 。

1.3 执行过程中数据库进程异常

这通常表现为数据库halt、段错误、PAGE FAULT、线程污染(TAINED)或OOM错误 。具体内容参见第二部分实例故障 。

第二部分 实例故障

实例故障指数据库进程dmserver出现异常,表现为异常中止、进程存在但无响应或无法登录 。

2.1 异常中止

可以通过检查进程来确认数据库是否异常中止 。如果ps -ef|grep dmserver命令没有返回dmserver进程信息,则说明数据库已异常中止 。

2.1.1 数据库halt

数据库在运行中会进行实时检查,如授权、文件完整性、内存污染和数据页校验等 。当检测到严重问题时,数据库会主动"自杀"(halt)以防止更严重的错误发生 。

排查方法:查看数据库运行日志(如 dm_DMSERVER01_202103.log),搜索 "halt" 关键字 。halt信息前通常会有具体的原因说明 。

cat /home/dmdba/dmdbms/log/dm_DMSERVER01_202103.log | grep halt

对于其他类型的错误,如果数据库日志中没有明显信息,可以查询操作系统日志(通常是 /var/log/messages*),搜索 dmserver 的进程号或 "DM" 相关信息 。

cat /var/log/messages* | grep DM

2.1.2 段错误

段错误可能由两种情况引起:一种是数据库halt时主动进行除0操作引发的异常;另一种是数据库自身BUG导致的内存写溢出、越界或空指针操作 。后者发生时,通常日志中无记录,但会在bin目录下生成一个core文件 。这通常与操作系统、CPU与数据库软件版本的兼容性有关,建议更换软件版本或操作系统 。

2.1.3 PAGE FAULT

当发生PAGE FAULT时,通常会伴随一个错误码 。

Code 0:通常表示无法申请到所需内存,需要修改ini配置以调整内存使用量 。
其他Code:基本是由于内存读写越界引起的 。
2.1.4 线程污染 (TAINED)

如果操作系统日志中出现DM相关线程被"tained"的信息,通常是由于第三方软件(如杀毒或安全软件)污染了DM线程,导致其被异常中止 。这会产生不可预期的后果,需要调整环境,避免第三方软件影响数据库进程 。

2.1.5 OOM错误

OOM(Out of Memory)是操作系统的自我保护机制,当某个进程占用大量内存时,可能会被操作系统中止以释放内存 。如果数据库进程频繁被OOM kill,需要调整数据库和操作系统的内存相关参数 。

2.2 连接异常

可以使用本地disql工具测试连接是否正常 。

home/dmdba/dmdbms/disql SYSDBA/SYSDBA@127.0.0.1:5236

2.2.1 配置不正确

大多数连接异常是由于配置不当造成的 。数据库进程看似正常,但新建连接会失败 。

常见原因:

最大连接数限制:dm.ini中的MAX_SESSIONS参数限制了最大连接数 。达到上限后,数据库会拒绝新连接,并在日志中记录 "reach max session limit" 。
查看MAX_SESSIONS设置:

select * from v$dm_ini where para_name='MAX_SESSIONS';

查看当前连接数:

select count(*) from v$sessions;

操作系统用户资源限制:操作系统的Open files限制过小,会导致创建线程失败,从而无法连接数据库 。这通常会在数据库日志中看到 "create thread failed" 的信息 。
查看dmserver进程的资源限制(假设进程号为1199) :

cat /proc/1199/limits

查看进程已打开的句柄数 :

ls -l /proc/1199/fd | grep -c ">"

如果已打开的句柄数达到或超过了limits中的限制,需要修改系统配置(如 ulimit -n 65535)并重启数据库进程 。
2.2.2 数据库缺陷

如果排除了配置问题,且连接时长时间不成功也不返回错误,很可能是由于数据库自身的缺陷,导致登录过程中发生资源等待或死锁 。

第三部分 人为操作

人为操作导致的故障主要涉及误删除文件和误修改数据 。

3.1 误删文件

3.1.1 执行文件

在Linux环境下,即使数据库进程正在运行,其相关的可执行文件也可能被删除 。程序会继续运行,但日志等文件可能在程序结束后丢失 。可以通过进入/proc/<pid>/cwd路径下,拷贝相关文件进行备份 。

3.1.2 dm_service.prikey

该文件是实例的RSA密钥文件,用于重要数据的加解密 。误删除后无法简单恢复,需要重新初始化实例 。

3.1.3 控制文件

控制文件 (dm.ctl) 记录了实例信息、数据版本以及数据文件和重做日志文件的路径等 。如果被误删,可能导致数据文件、REDO日志文件脱离数据库实例的管理,引发严重问题 。应尽快从dm.ini中配置的备份路径下找到最新的ctl备份文件进行恢复 。

3.1.4 重做日志文件

重做日志文件(如 实例名.log)记录了对数据文件的修改信息 。如果被误删,未写入数据文件的日志信息将丢失,并可能导致数据库无法启动 。

首选恢复方式:通过备份和归档进行恢复 。
应急处理(备份不可用时):通过替换重做日志文件来启动数据库 。
使用dminit初始化一个配置相同的新实例 。
启动并停止新实例一次 。
将新实例的重做日志文件拷贝到故障库目录下 。
使用dmmdf工具查看故障库的数据文件信息 。
使用dmmdf工具修改新重做日志文件的两个magic值,使其与故障库信息一致 。
修改后,数据库即可正常启动 。 注意:此方法不适用于集群环境,且仅为临时方案,需尽快将数据迁移至健康环境 。
3.1.5 数据文件

如果DBF文件在运行中被误删,首选方式是通过备份进行时间点恢复 。若备份不可用,应立即停止所有对数据库的写操作 。在Linux环境下,可以尝试从/proc中的文件镜像进行冷拷贝来还原 。

3.2 误修改、删除数据

如果误操作的事务未提交,可以直接ROLLBACK回滚 。
如果事务已提交,最安全的方法是通过备份恢复 。
3.2.1 插入

对于错误的批量插入,可以利用DM每行数据都存在的trxid伪列,通过查询相关事务号进行分组,以识别并清理问题数据 。

3.2.2 删除

数据被DELETE并提交后,实际数据行会被打上删除标记,在undo_retention配置的时间后才会被完全清理 。

闪回查询:如果开启了闪回功能,可以直接查询指定时间点的数据并恢复 。
逻辑附加归档:如果开启了逻辑附加归档,可以使用dbms_logmnr工具分析归档日志,获取数据用于回填 。
3.2.3 更新

对于UPDATE误操作,如果不满足上述恢复条件,但存在物理归档,可以使用dmlcvt工具分析ROLL.DBF(表空间号为1)的所有记录 。在分析结果中找到所有urec_upd类型的记录,这些记录包含了更新的KEY和旧值信息,可用于数据还原 。

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服