第一章 达梦日志审核问题
随着SQM版本的迭代,所支持的数据库及审核类型越来越多。在近期版本中则增加了对达梦库的审核功能。具体审核方式为审核达梦数据库的跟踪日志文件。分析文件中的慢SQL,分析违反规则、执行计划、相关对象等信息。
经过测试,SQL的违反规则和相关对象均可以顺利展示。目前发现的主要问题是大部分业务SQL的执行计划均无法获得。

查询监听日志中有大量的如下报错信息。

为了搞清楚问题原因,因此通过一条典型SQL做相应的测试。
第二章 连库分析问题原因
在确保连库采集用户授予了相应采集权限后,通过采集用户sqm登录审核目标库。
grant select on V$DM_INI to sqm;
grant select on v$version to sqm;
grant select on V$SQL_NODE_NAME to sqm;
grant select any table to sqm;
grant select any view to sqm;

尝试直接查询或EXPLAIN目标SQL解析执行计划:

会提示找不到目标表相关对象。
查询相应对象所属用户:

可以看到相应表均属于XXTEST业务用户。而当前是通过SQM用户去测试的,因此找不到用户也属于正常。

那基于本章节的测试,目前获取不到执行计划的主要原因是采集用户下没有SQL相关的表对象。下面分析解决办法。
第三章 解决方案
3.1 增加切换schema步骤
为了获得目标业务用户的所属对象,需要切换到对应用户下。因此尝试增加如下切换用户步骤:
set schema XXTEST;
alter session set current_schema=XXTEST;
切换用户测试:

经过测试,无法切换到对应业务用户。原因是对应模式不属于当前用户。即使通过SYSDBA登录,也是同样的现象。
通过查阅技术资料及与达梦原厂人员沟通,只有由自己用户创建的schema之间可以互相切换。其他用户下的schema均没有权限切换。
具体参见达梦技术文档:
https://eco.dameng.com/community/article/7663df9b6404dfd2e8c8b593183f6ec4

因此这种方案,除非是指定模式是由自己用户创建的,才可以通过上述命令切换。很显然,实际的场景是业务用户及模式已经先一步创建,之后才创建采集用户。我们希望通过采集用户
set schema schema_name;
切换到不属于自己用户下的模式,很显然是无法完成的。也就无法获得对应模式下的SQL执行计划。
3.2 给表名加上schema前缀
EXPLAIN SELECT COUNT(*)
FROM XXTEST.HrmMain
WHERE status IN (0, 1, 2, 3)
AND loginid IS NOT NULL
AND (Accounttype IS NULL OR Accounttype != 1)
AND NOT EXISTS
(SELECT 1
FROM XXTEST.HrmMainVirtual a, XXTEST.Hrmcustomr b
WHERE HrmMain.id = a.resourceid
AND a.virtualtype = -10000
AND NOT EXISTS
(SELECT 1
FROM XXTEST.Hrmcustomr
WHERE a.departmentid = crmmanagerdeptid));

通过表名增加模式名的办法,在采集用户sqm具有访问对应表权限的情况下,很显然是可以获得执行计划的,但这样处理的方法较为复杂,需要在SQL中用到的每张表前都增加模式名。从软件处理上较为不方便。
3.3 获取业务用户密码
通过上述两种方法,均不能很好的解决“获取不到执行计划”的问题。这里分析,只有对应用户才能直接访问用户下所属表的。因此索要业务用户密码,使用业务用户作为SQM的采集用户,是可以顺利解决获取执行计划问题的。
但又存在以下问题:
1.如果所属SQL在多个业务用户下,那单个业务用户也是无法满足需求。
2.索要业务用户密码,不符合应用安全规范。
因此这种方案,某种情况下可行,但不符合安全规范。
3.4 采集用户下建立同名同义词
通过采集用户下建立对应表的同义词。通过访问同义词来直接获得表信息。从而达到获取目标SQL执行计划的目的。
为此需要根据目标SQL所涉及到的表,编写采集脚本建立同义词:

建立同义词后,直接访问采集用户下的同义词对象,即直接访问到了对应业务用户下的表对象。

在采集用户下执行测试:
EXPLAIN SELECT COUNT(*)
FROM HrmMain
WHERE status IN (0, 1, 2, 3)
AND loginid IS NOT NULL
AND (Accounttype IS NULL OR Accounttype != 1)
AND NOT EXISTS
(SELECT 1
FROM HrmMainVirtual a, Hrmcustomr b
WHERE HrmMain.id = a.resourceid
AND a.virtualtype = -10000
AND NOT EXISTS
(SELECT 1
FROM Hrmcustomr
WHERE a.departmentid = crmmanagerdeptid));

相应的SQL执行计划可以顺利获得。
但此种办法也有一定限制:
如果同名表对象在多个业务用户下,那一组同名表也只能建立其中一个同义词。其他未建立同义词的表仍然是有问题。
第四章 问题总结
通过上述章节的方案测试,最终商讨后确定在采集用户下创建同义词的方式,可以用较小的代价来获得目标SQL的执行计划。
但经过实际测试:

使用采集用户SQM手动执行的业务SQL,其执行计划是正常的。
但业务用户执行的相同SQL,却仍然是获取不到执行计划。
这里分析可能是由于SQM在获取执行计划时,会提前切换到对应用户下。
alter session set current_schema=XXTEST;
但目前的情况切换时会报“模式[XXTEST]不属于当前用户”的问题。导致返回报错,从而无法继续获得采集用户下的同义词对象信息。具体是否是这里的原因,还需要产品同事进一步测试验证。从而找到修复方案。




