当前位置: 首页 > news >正文

达梦8数据库常见故障分析与解决方案

达梦数据库(DM)作为国产数据库的代表之一,广泛应用于政府、金融等行业中。由于其较为复杂的架构和配置,故障分析显得尤为重要。以下是针对 达梦8 数据库的故障分析方法,涵盖了 SQL 类、实例类和人为操作类故障的处理步骤。

第一部分 SQL类故障

SQL类故障主要有三种类型,分别是:结果集异常、执行长期没有返回数据、执行过程中数据库进程异常等三种情况

1.1 结果集异常

首先我们要定位到结果集异常的语句,可以通过应用日志、驱动日志、数据库SQL日志、VSQLHISTORY视图等方法找到该语句。一般情况下,结果集异常大部分是由于优化器对查询语句的错误改写或者优化导致的,我们尽量保证提取到的语句和实际执行的语句是严格一致、绑定参数相同、数据库参数一致,这样可以保证我们进行验证时能准确的复现问题。在计划一致的情况下,如果可以重现查询结果集异常的情况,我们可以尝试对异常的查询语句进行裁剪,也可以参照当前计划,有目的修改通过SQL语句摘除计划中的某些操作符,一步步的得到导致结果集出错的最精简语句。然后通过修改参数、/HINT/、改写语句等方式,调整问题操作符为等价的其他操作符来解决问题。查看vSQL_HISTORY 视图等方法找到该语句。一般情况下,结果集异常大部分是由于优化器对查询语句的错误改写或者优化导致的,我们尽量保证提取到的语句和实际执行的语句是严格一致、绑定参数相同、数据库参数一致,这样可以保证我们进行验证时能准确的复现问题。在计划一致的情况下,如果可以重现查询结果集异常的情况,我们可以尝试对异常的查询语句进行裁剪,也可以参照当前计划,有目的修改通过 SQL 语句摘除计划中的某些操作符,一步步的得到导致结果集出错的最精简语句。然后通过修改参数、/HINT/ 、改写语句等方式,调整问题操作符为等价的其他操作符来解决问题。 查看vSQLHISTORY视图等方法找到该语句。一般情况下,结果集异常大部分是由于优化器对查询语句的错误改写或者优化导致的,我们尽量保证提取到的语句和实际执行的语句是严格一致、绑定参数相同、数据库参数一致,这样可以保证我们进行验证时能准确的复现问题。在计划一致的情况下,如果可以重现查询结果集异常的情况,我们可以尝试对异常的查询语句进行裁剪,也可以参照当前计划,有目的修改通过SQL语句摘除计划中的某些操作符,一步步的得到导致结果集出错的最精简语句。然后通过修改参数、/HINT/、改写语句等方式,调整问题操作符为等价的其他操作符来解决问题。查看vsql_history视图
打开数据库监控参数,默认为开启状态

SQL> alter system set 'ENABLE_MONITOR'=1;

应用执行相关问题模块,然后查看v$sql_history,通过SQL_ID, SESS_ID,TRX_ID,TOP_SQL_TEXT, START_TIME等字段定位语句

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

某些信息没有及时更新也可能出现结果集异常,如:查询涉及到全文索引没有更新、查询涉及到的物化视图没有更新、错误的使用确定性函数标记了不确定函数、非一致读备机查询数据存在延迟。

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

如果SQL执行长时间没有返回数据,可能由以下情况造成:所执行语句本身存在性能问题、执行过程中某些对象/资源发生等待,其他特殊情况等。

1.2.1 性能问题

先根据vsessions视图确认语句是否处于活动状态,再根据活动语句的trxid在vsessions视图确认语句是否处于活动状态,再根据活动语句的trxid在vsessions视图确认语句是否处于活动状态,再根据活动语句的trxidvtrxwait视图中查询语句是否存在等待,没有查询结果的话就是语句没有发生等待。如果语句活动中,且没有发生等待,那大概率是存在性能问题,需要对语句进行调优。
通过state字段查询语句是否在ACTIVE状态

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 '%语句片段%';

根据获取到的trxid查询是否处于等待状态

SQL> SELECT * FROM v$trxwait WHERE id = 上面SQL获取到的trx_id
1.2.2 发生等待

如果语句处于活动状态,且在vtrxwaitc查询中有返回记录,说明语句有等待发生,然后通过WAITFORID字段到vtrxwaitc查询中有返回记录,说明语句有等待发生,然后通过WAIT_FOR_ID字段到vtrxwaitc查询中有返回记录,说明语句有等待发生,然后通过WAITFORID字段到vsessions中定位到所等待的会话信息,一般来说,都是因为某些会话或者客户端忘记进行提交或者回滚操作,后续就一直空闲了,导致其他的事务由于跟该事务存在一些事务上的依赖关系发生等待,针对这种情况,我们需要在确认安全的情况针对这个阻塞源头会话进行操作,关闭客户端 /CLOSE 会话/发送提交或者回滚命令等。
另外一种等待不会通过 VTRXWAIT查询得到结果,比如某些表发生DDL操作过程中,其他的会话尝试对该表进行查询,由于字典对象发生变化,所以发生字典对象的等待,这种阻塞可以通过查询SELECT∗FROMvTRXWAIT 查询得到结果,比如某些表发生 DDL 操作过程中,其他的会话尝试对该表进行查询,由于字典对象发生变化,所以发生字典对象的等待,这种阻塞可以通过查询 SELECT * FROM vTRXWAIT查询得到结果,比如某些表发生DDL操作过程中,其他的会话尝试对该表进行查询,由于字典对象发生变化,所以发生字典对象的等待,这种阻塞可以通过查询SELECTFROMvlock WHERE blocked = 1 来进行确认,查询结果中可以对相关锁对象的持有事务来查询 V$SESSIONS,来确认阻塞来源。
一般情况下这种 DDL 导致的等待会有一个显示的等待时间,由 dm.ini 参数 DDL_WAIT_TIME 来进行控制,默认是 10,也就是说如果等待 10 秒钟后,阻塞源头的 DDL 还没有执行完释放资源,会抛出锁超时错误。
通过state字段查询语句是否在ACTIVE状态

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 '%语句片段%';

根据获取到的trxid查询是否处于等待状态

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

然后根据vtrxwait视图中获取到的waitforid字段在vtrxwait视图中获取到的wait_for_id字段在vtrxwait视图中获取到的waitforid字段在vsessions定位到会话

SQL> SELECT * FROM v$sessions WHERE trx_id = 查询到的 WAIT_FOR_ID
1.2.3 特殊情况

还有一些其他情况造成的等待:
(1)查询中由于存在临时表 /SORT/HASH JOIN/HAGR 等操作导致使用的临时表空间,INI 参数又限制了 TEMP 表空间大小,在临时表空间没有被其他会话使用完并释放时发生等待。
(2)主备、读写分离等环境运行过程中,由于备机自身或者配置相关的原因(备机 IO 出现异常、主备网络异常、数据延迟达到配置的主备最大延迟)等,导致主机上运行一些需要刷 REDO 日志的语句发生等待,这种等待需要备机上的这些现象缓解之后才会解开。
(3)大表发生 DELETE 量数据、TRUNCATE 后,对该表的查询或者 DML 操作缓慢,这个时由于大批量删除数据之后,由于这些数据都只是被标记删除,在一定事件后会由回收站进行统一的清理操作,清理过程中需要对数据页进行修改,而涉及的数据页又非常多,所以导致执行速度缓慢。
(4)数据库自身 BUG 导致的死锁,正常情况下,如果存在某些事务互相等待的情况,数据库会主动抛出死锁报错,但是如果时数据库内部自身 BUG,导致自身的一些临界区资源出现死锁,是不能自动处理的,一般我们最后考虑这种情况。

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

一般可分为以下几种:运行过程中数据库发生 halt、运行过程中数据库段错误、运行过程中发生PAGE FAULT、运行过程中发生线程污染(TAINED)、运行过程中发生 OOM 错误,具体信息可以看第二部分实例故障。

第二部分 实例故障

DM 实例故障,即数据库进程 dmserver 出现异常,表现为异常中止,进程存在但无响应或者无法登录的状态,出现此类问题都属于比较严重的故障,一般情况下我们需要尽可能的收集到所需要的信息进行故障分析,这里我们将把故障分为两类,一种是数据库异常中止,一种是连接异常。

2.1 异常中止

数据库异常时,可以通过查看进程来确认数据库是否异常中止

shell> ps -ef|grep dmserver
dmdba     1199     1  0 09:06 ?        00:00:00 /home/dmdba/dmdbms/bin/dmserver /data/DAMENG/dm.ini -noconsole
root      1430  1388  0 09:07 pts/0    00:00:00 grep --color=auto dmserver

没有dmserver进程信息的,说明数据库已经异常中止

2.1.1 数据库halt

数据库实例在运行过程中会实时进行一些检查,比如授权过期信息、文件完整性信息、内存是否污染信息、数据页校验信息等,如果出现一些比较严重的问题被数据库自查到,数据库自身会选择自杀并给出提示信息,来防止更严重的错误产生。对于数据库halt类型的错误,我们可以通过查看数据库的运行日志,搜索 halt,如果发现存在 halt 字样的日志内容,会在 halt 之前又具体的 halt 原因说明,这个是数据自己保证数据安全的一种方式,当检测到一些严重异常时,采取自杀的方式来保全数据,防止更进一步的异常。
查看数据库日志抓取halt信息,日志命名方式为 dm_实例名_年月.log

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

对于其他几种类型的错误,我们从数据库运行日志中一般不会发现明显的信息,都是运行日志刷新过程中突然中断了,这些错误我们可以通过查询操作系统日志(一般是 /var/log/messages*),然后搜索异常前的 dmserver 的进程号或者搜索 DM 相关的信息,根据查询到的信息不同的类型进行不同的处理。
查看系统日志,搜索DM异常信息

cat /var/log/messages* |grep DM
2.1.2 段错误

一种是因为 halt 时,通过主动进行除 0 操作引发的异常,另一种是由于数据库自身 BUG,导致发生内存写溢出、越界、空指针操作等引起的异常。
第二种情况发生时通常数据库日志、系统日志中均没有相关记录,会在bin目录下生成一个core文件,通常是因为操作系统、cpu与数据库软件版本的兼容性有关,建议更换数据库软件版本或操作系统。

2.1.3 PAGE FUALT

一般 PAGE FUALT 后会跟有具体的错误码,code: xx,在 LINUX 内核中定义了这些报错对应的内容。
如果 code 是 0,一般是由于数据库运行中没有办法申请到需要使用的内存导致,这种时候需要考虑修改 INI 相关配置,调整数据库的内存使用量。其他几种 code 或者是 code 的组合(比如 6 = 4 + 2 表示存在两种错误),基本是发生内存读写越界引起。

2.1.4 线程污染TAINED

如果操作系统日志中出现了 DM 相关线程 tained 相关的信息,一般是由于第三方软件(主要是杀毒软件或者安全软件),对 DM 的相关线程进行污染,导致数据库的一些线程被异常中止,不同类型的线程被中止可能导致不同的结果,而且是不可预期的,这种情况下需要及时调整现场的环境,让相关软件尽量不影响数据库进程

2.1.5 OOM错误

OOM 操作系统本身对于自己的一种保护机制,对占用大量内存的进程,如果满足一定条件,就会被操作系统中止,腾出空余内存,如果频繁发生数据库进程被 oom kill,则需要调整数据库内存相关参数,操作系统内存相关参数等,防止数据库进程被频繁 oom。

2.2 连接异常

使用本地disql工具连接数据库,测试连接是否异常
SYSDBA/SYSDBA为数据库用户名和密码,5236为数据库端口号

shell> home/dmdba/dmdbms/disql SYSDBA/SYSDBA@127.0.0.1:5236
2.2.1 配置不正确

大多数情况下,连接异常类问题都是由于配置不正确导致。具体的表现:在任务管理器中查看 dmserver 进程能够看到正常的 CPU 活动信息,查看磁盘网络等活动也存在正常的波动,但是新建连接连接数据库会提示网络通讯异常。
常见原因:
(1)dm.ini 中限制了最大连接数(相关参数 MAX_SESSIONS),数据库连接达到该值后会拒绝创建新连接,在数据库运行日志中会发现 reach max session limit 相关日志。
查看MAX_SESSIONS信息

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

查看当前连接数

select count(*) from v$sessions;

(2)由于操作系统的用户资源限制引起,我们通过命令 cat /proc/dmserver 的 pid/limits 可以查看到当前数据库进程的一些资源限制,我们主要关注的是 Open files 这个限制,由于在 DM 中每一个会话都是一个线程,一个线程在 linux 中需要一个独立的文件句柄去控制,如果该项限制太小,会导致创建线程失败,从而在外部显示为连接数据库失败,这种情况一般在数据库运行日志中会有 create thread failed 相关信息,并且检查进程 limits 会发现 Open files 限制的较小,通过 ls -l /proc/dmserver 的 pid/fd|grep -c 命令,查看数据库已经打开的句柄以及等于或者超过 limits 值,由于这些 limits 是在进程启动时生效的,不能动态修改,如果已经出现了这种现象,只能修改相关的配置(ulimit -n 65535等命令),并且重启数据库进程。
查看dmserver资源限制,1199为dmserver的进程号

Limit                     Soft Limit           Hard Limit           Units     
Max cpu time              unlimited            unlimited            seconds   
Max file size             unlimited            unlimited            bytes     
Max data size             unlimited            unlimited            bytes     
Max stack size            8388608              unlimited            bytes     
Max core file size        unlimited            unlimited            bytes     
Max resident set          unlimited            unlimited            bytes     
Max processes             39419                39419                processes 
Max open files            1024                 4096                 files     
Max locked memory         65536                65536                bytes     
Max address space         unlimited            unlimited            bytes     
Max file locks            unlimited            unlimited            locks     
Max pending signals       39419                39419                signals   
Max msgqueue size         819200               819200               bytes     
Max nice priority         0                    0                    
Max realtime priority     0                    0                    
Max realtime timeout      unlimited            unlimited            us

查看进程已打开句柄数

shell> ls -l /proc/1199/fd|grep -c ">"
2.2.2 数据库缺陷

还有些情况是由于数据库自身的缺陷引起,如果出现连接异常,检查数据库配置以及操作系统配置没有发现异常,并且连接数据库时长期不成功也不返回报错,这种情况大概率时由于数据库自身的原因导致客户端连接过程中发生资源等待或者死锁,导致登录消息一直陷入在资源/临界区等待状态。

第三部分 人为操作

DM 数据库实例包含数据文件部分和执行文件,执行文件即通过 DM 的安装包安装后在目标机器上存在的可执行程序以及动态库,数据文件是通过 DM 的实例初始话工具初始化的实例文件,包含数据文件(DBF 文件)、配置文件(ini 文件)、控制文件(ctl 文件)以及一些其他必须的文件 (dm_service.prikey) 等,若此类文件在运行过程中被误删除,可能导致异常的情况。
另外在运维过程中,可能存在对数据的误操作,更新、删除插入等,如果存在这种情况,也可能导致应用系统的问题。

3.1 误删文件

3.1.1 执行文件

在 Windows 环境下,执行文件在被引用过程中是无法被删除的,出现此类问题的情况比较少,但在 Linux 环境下,数据库进程存在的情况下,相关执行文件可以被删除,程序会继续运行,但是运行过程中的日志等文件在程序执行完后可能会丢失,此中情况下,通过查询 dmserver 的进程 pid,然后进入到 /proc/pid/cwd 路径下,依然可以看到执行过程中依赖的相关文件,可以通过拷贝命令将相关文件拷贝存放,供后续使用。

3.1.2 dm_service.prikey

该实例的 RSA 钥文件,涉及基本的数据库一些重要数据的加解密,误删除无法简单处理,需重新初始化实例。

3.1.3 控制文件

控制文件,即 dm.ctl,记录数据库实例的实例相关信息、数据版本信息和重做日志文件、数据文件路径属性等,如果被异常删除,表空间属性相关修改可能出现异常,如果不能正常修复,可能导致某些数据文件、REDO 日志文件没有被数据库实例纳入到管理范围,引发其他的严重问题。
如果发现(一般在巡检中)该文件被异常删除,需要及时对该文件进行修复,DM 数据库自身定期会对该文件进行备份,ctl 的备份路径可以在 dm.ini 中进行配置,在该目录下找到最接近故障时间的 ctl 备份文件进行恢复。

3.1.4 重做日志文件

默认在数据库实例下存在以实例名 .log 命名的重做日志文件,该文件记录的是数据库运行过程中对实际的数据文件修改的日志信息,并且相关的修改信息达到一定的条件才会实际被应用在数据文件上,如若发生误删除,首先在日志上这些部分未应用日志信息涉及的数据一定就丢失了,另外可能导致数据库无法正常启动。
首选的恢复方式是通过备份还原,由于归档文件中如实的记录了重做日志的信息,所以 REDO 中涉及的数据通过备份还原并对归档的读取可以正常的将数据库恢复。
如果备份还原不可用,或者归档丢失等,只能通过替换重做日志文件的方式对库做应急处理,如下所示:
(1)通过 dminit 工具初始化一个新的实例,相关参数参考目前故障库的 dminitxxxx.log 中的配置保持一致。
(2)将新建实例正常启动并停止一次。
(3)将新实例的重做日志文件拷贝到故障库下。
(4)通过 $DM_HOME/bin 目录下的 dmmdf 工具查看故障库的数据文件的相关信息。
(5)用 dmmdf 工具按照前面查到的信息对拷贝过来的新重做日志文件修改两个 magic 值。
(6)修改完成后,数据库可以正常启动。
此类方法在集群环境下不适用,由于重做日志记录的部分头部信息和实例间同步相关,新建重做日志会导致集群不可用,另外这种方法只能临时用于启动数据库,需要尽快将数据迁出至健康环境。

3.1.5 数据文件

如果运行过程中 DBF 文件被误删除,首选的方式是通过备份还原对数据库进行最大长度的恢复(指定时间点),如果备份不存在或者不可用,在可能的情况下,尽可能快的停止一切对数据库的写操作(切断应用、网络),同样,如果在 Linux 环境下,可能对该文件还存在镜像,可以从 proc 中进行冷拷贝操作尝试还原。

3.2 误修改、删除数据

如果存在误操作,并且语句没有提交的,可直接rollback进行回滚,如果出现误操作并提交,最安全的办法依然是通过备份恢复到尽可能新的状态,如若备份、归档存在问题,则需要其他的方式进行处理。

3.2.1插入

对于错误插入,在 DM 的每一行数据上,都存在 trxid 伪列,一般情况误插入如果是批量的,通过查询相关事务号进行分组,确认批量行数,结合检查数据一般是可以找到问题数据再进行清理。

3.2.2删除

当数据发生删除并提交时,实际的数据还是存在于数据文件上的,只是该行数据被打上了删除标记,被打上删除标记的数据对查询是不可见的,并且在 ini 配置的 undo_retention 时间后,有删除标记的数据会被完全清理,在数据文件上就不可见了。如果启用了闪回查询,出现此类问题时,直接通过闪回查询指定时间点,可以将不可见的数据直接返回到数据库客户端上(UPDATE类似),然后将这些数据进行落地保存,用于后续的修复。
如果开启了逻辑附加归档,可以通过 dbms_logmnr 工具对逻辑附加归档进行分析,分析完成后获取相关数据信息,用于数据回填。

3.2.3更新

如果是 UPDATE 误操作,且不满足以上几种恢复的条件,如果存在物理归档,可以通过 $DM_HOME/bin 目录下的 dmlcvt 工具对归档进行分析(具体用法参考 dmlcvt help),分析表空间号为 1(ROLL.DBF)的所有记录,分析完成后,在分析结果中找到所有的 urec_upd 类型记录,该记录包含了更新涉及的 KEY,以及更新的旧值信息,使用这些信息还原更新。
在处理 SQL 类故障实例故障人为操作 方面的故障时,最重要的是保持冷静、系统地排查问题,并结合丰富的工具和日志资源,确保能够精准定位问题的根本原因。无论是性能问题、系统资源的瓶颈,还是因人为操作引发的数据异常,都需要有条理地逐步解决。

总结建议

  1. 备份与恢复: 在所有操作中,始终保持最新的备份。及时备份数据文件、控制文件和日志文件是避免灾难性故障后果的最有效手段。

  2. 系统监控与日志分析: 配置完善的监控系统,定期查看关键系统的运行状况。

  3. 应急响应: 针对各种故障,尽量提前准备好应急方案,并定期进行故障演练,确保在出现故障时能迅速反应,减少系统停机时间。

  4. 问题复现与调优: 当问题复现时,要确保测试环境和生产环境的一致性,以便能够准确诊断。对于慢查询、死锁等常见问题,调优建议应结合实际工作负载和业务需求,逐步推进。

通过持续的监控、系统优化和故障应急演练,能够将数据库故障的风险降到最低,确保系统的稳定性和可靠性。同时,通过不断总结经验,优化流程,将能够有效提高团队应对复杂数据库问题的能力。
hhh6.jpg

http://www.dtcms.com/a/502876.html

相关文章:

  • 迁移服务器
  • 解决docker构建centos7时yum命令报错、镜像源失效问题
  • 密钥轮换:HashiCorp Vault自动续期,密钥生命周期?
  • 即时通讯系统核心模块实现
  • 【HarmonyOS】组件嵌套优化
  • 福州企业做网站催眠物语wordpress
  • 图文并茂:全面了解UART相关知识(TTL+RS232+RS484)
  • VMware Euler系统Ctrl+C/V共享剪贴板完全指南:从配置到彻底清理
  • IOT项目——STM32
  • 【物联网架构】
  • 【编程】IDEA自定义系统注解格式|自定义自定义注解格式
  • 定位网站关键词dw网页制作模板源代码
  • 【Linux网络】封装Socket
  • Solidity智能合约开发入门攻略
  • AI决策系统:从数据到行动的智能跃迁——底层逻辑与实践全景解析
  • 好看的单页面网站石岩网站设计
  • 未来的 AI 操作系统(二)——世界即界面:自然语言成为新的人机交互协议
  • 经典排序算法的实现与解析
  • 流量转化与生态重构:“开源AI智能名片链动2+1模式S2B2C商城小程序”对直播电商的范式革新
  • Docker 常用命总结
  • git 和 tortoisegit的快速使用教学(上传至gitee或GitHub)
  • 基于单片机的智能家居多参数环境监测与联动报警系统设计
  • OpenHarmony 6.0 低空飞行器开发实战:从AI感知检测到组网协同
  • 专业做网站排名的人做短视频网站
  • 从协议到工程:一款超低延迟RTSP/RTMP播放器的系统级设计剖析
  • Visio 2024 下载安装教程,安装包
  • 郑州做网站公司+卓美电子商务网页设计试题
  • Java 大视界 -- 基于 Java 的大数据实时流处理在工业物联网设备状态监测中的应用与挑战
  • ESP3266 NodeMCU 使用Arduino点亮 ST7789 240x240 tft屏
  • OpenHarmony平台大语言模型本地推理:llama深度适配与部署技术详解