Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1693563
  • 博文数量: 136
  • 博客积分: 10021
  • 博客等级: 上将
  • 技术积分: 3261
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-22 11:26
文章分类

全部博文(136)

文章存档

2010年(1)

2009年(26)

2008年(109)

我的朋友

分类: Oracle

2008-05-08 22:10:51

今天解决了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 次。

 

修改一下业务逻辑就好了。

 

(上面的查询是从测试库获取的数据,生产库中,这个数值应该要大得多。)

阅读(3444) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~