今天解决了3个 Oracle 的问题:
1. 重建 10g 控制台
2. EXP/IMP 的字符集问题
现场人员报告 DMP 文件导入 Oracle 后,存储过程的中文注释产生乱码,表、列的注释也是样。
这个 DMP 是从 Windows 上导出的,在 Linux 上导入时出现该问题。抓取的部分错误如下:
|
……
IMP-00003: ORACLE error 911 encountered
ORA-00911: invalid character
IMP-00017: following statement failed with ORACLE error 4043:
"ALTER PROCEDURE "PRC_T_PERSON_ID_????" COMPILE REUSE SETTINGS TIMESTAMP '20"
"07-05-14:18:29:36'"
IMP-00003: ORACLE error 4043 encountered
ORA-04043: object PRC_T_PERSON_ID_???? does not exist
About to enable constraints...
Import terminated successfully with warnings.
…… |
初步判断是字符集的问题。于是在两个数据库服务器上分别获取其字符集,发现二者相同,都是ZHS16GBK:
|
SQL> select userenv('language') from dual;
USERENV('LANGUAGE')
-------------------------------------------
SIMPLIFIED CHINESE_CHINA.ZHS16GBK |
那么查看各自的客户端字符集。从 Windows 的环境变量“HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOME0”里,看到 NLS_LAN 的设置也是 ZHS16GBK;而现场人员从 Linux 里获取到的客户端字符集为 UTF8。
问题就出在这里了,这个 DMP 是从 Windows 上导出的,然后在 Linux 上执行导入操作,由于客户端字符集不一致,导致出现乱码。
使用 Windows 做客户端重新执行导入操作,问题解决。
3. SQL优化
现场人员报告原来系统很好,从1.6.1版本升级到1.6.2后,核心业务变得很慢,慢到客户都没耐性等它做完,半小时后就直接关闭系统了。
从视图 v$session_wait 中获取该会话正处于 db file sequential read 等待。从 v$session.sql_address 中抓取 SQL 地址,然后从视图 v$sqlarea 中得到该SQL为:
|
update ac01 set akc023 = n_akc023 where aac001 = v_aac001; |
当时觉得很奇怪,这个 SQL 怎么会产生等待呢?于是再通过如下 SQL 找到各个性能指标最高的执行 SQL:
|
SQL> SELECT MAX(DISK_READS) DISK_READS,
2 MAX(BUFFER_GETS) BUFFER_GETS,
3 MAX(ROWS_PROCESSED) ROWS_PROCESSED,
4 MAX(EXECUTIONS) EXECUTIONS
5 FROM V$SQLAREA;
DISK_READS BUFFER_GETS ROWS_PROCESSED EXECUTIONS
---------- ----------- -------------- ----------
109547 36286762 9020860 9020860
SQL> select sql_text from v$sqlarea where EXECUTIONS >= 9020860;
SQL_TEXT ---------------------------------------------------------
update ac01 set akc023 = n_akc023 where aac001 = v_aac001;
SQL> |
执行次数(EXECUTIONS)最高的 SQL,居然还是这条简单的更新语句,而且 aac001 上建立了索引的。
查询系统的版本更新记录,发现开发人员这次就是更新了这个。那么问题基本就出在这里了。
查看编写的代码,发现该 SQL 是放在过程 A 的 FOR 循环里的,而过程 A 被另一个过程 B 调用。不幸的是,过程 A 又被放在了 B 的一个循环中,这是不应该的。
所以,一个7000人的单位,本来只需要更新7000次,现在却要更新 7000*7000 次。
修改一下业务逻辑就好了。
(上面的查询是从测试库获取的数据,生产库中,这个数值应该要大得多。)