关于Oracle 9i字符集问题的解决办法

日期: 2009-06-25 作者:佚名 来源:TechTarget中国 英文

  经常在项目实施完成后会发现中文字符在数据库里表现出乱码,有的甚至可以从客户端显示中文,但在服务端却显示出乱码,这种情况往往是项目实施完成后发现的,再次实施一方面麻烦,一方面可能会丢掉一部分数据,所以会感到不可处理。这次在emv根ca的部署中也遇到了同样的问题,不过这次被我解决了,写出来与大家一同共享,时间长了,我也就忘了,与大家分享,就当是大家为我保存信息了。

  如果要在Oracle数据库中使用中文字符,那么在安装操作系统时要安装中文语言包。并且在数据库所属的用户环境变量里指定所使用的中文字符集(一般使用GBK)。在安装数据库的过程中会有一个选择字符集的选项,但这个选项不是很明显,一般默认的是操作系统当前使用的语言环境,如果操作系统当前的语言环境不是中文GBK,那么在这里一定要选择。这次实施中我记得很清楚,我肯定安装时选择了语言,但安装到最后配置数据库时报了一个内存错误,这个我没有担心,数据库配置可以使用dbca再次配置。这种问题一般是系统参数有问题,仔细检查了system文件,果然有一个写错了。重启系统后,用dbca配置数据库实例,一路选择默认,很顺利,到晚上9点就把根ca和12张管理员证书签发了。按照计划,明天早上项目组的其它人员就可以测试了,我心里美滋滋地回家了。

  正当我准备测试的时候,格尔的人员发现昨天发的管理员在数据库里显示的是乱码,不是中文。不可能吗,安装时我明明选择了中文字符,当时我因为内存问题还让同事看来着,他还提醒我选择字符集了,怎么会错了?虽然在客户端看到了乱码,我还是不相信我安装错了,从数据库里查一下配置就知道了。首先检查数据库服务器的字符集select * from nls_database_parameters,从返回的结果检查NLS_CHARACTERSET是否zhs16gbk。这一查,我有点蒙了,当前的字符集是US7ASCII,并非zhs16gkb。到底是那个地方出错了,怎么会这样呢?也许是系统环境变量的问题,修改oracle用户的.profile文件,或者修改root用户的.profile-EIS试试。但是我怎么修改也不管用,格尔的人检查了我的配置和他们提交的文档里的不一致,加进了文档中的几个参数。当初认为他们的参数对oracle是不必要的,并且加进去会报错,所以注释了。格尔的人按照文档修改也不起作用,就建议我重装数据库,已经是10点了,如果重装,今天肯定不能测试了,项目组的测试人员都等着我了。我心里开始有点发急了,但很不甘心就这样重装,数据库的维护一直是我们的弱项,有一次练手的机会,一定要练练手。为了不影响进度,我让格尔的人在备份系统上部署,部署ca系统我已经重做了4次了,顶多一个小时就好。我集中精力处理故障,印象中字符集是可以修改的,但具体怎么改,得上网查资料。

  如何查看字符集设置?数据库服务器字符集select * from nls_database_parameters,其来源于props$,是表示数据库的字符集。客户端字符集环境select * from nls_instance_parameters,其来源于v$parameter,表示客户端的字符集的设置,可能是参数文件,环境变量或者是注册表。会话字符集环境 select * from nls_session_parameters,其来源于v$nls_parameters,表示会话自己的设置,可能是会话的环境变量或者是alter session完成,如果会话没有特殊的设置,将与nls_instance_parameters一致。客户端的字符集要求与服务器一致,才能正确显示数据库的非Ascii字符。字符集要求一致,但是语言设置却可以不同,语言设置建议用英文。如字符集是zhs16gbk,则nls_lang可以是American_America.zhs16gbk。

  如何修改字符集?8i以上版本可以通过alter database来修改字符集,但也只限于子集到超集,不建议修改props$表,将可能导致严重错误。 Startup nomount;? Alter database mount exclusive;? Alter system enable restricted session;? Alter system set job_queue_process=0;? Alter database open;? Alter database character set zhs16gbk;?

  我按照上面的方法修改,报错提示有活动得进程,不能修改,可我怎么也发现不了活动进程,数据库都重启过了,也不行。干脆重启系统吧。这次报了只能修改子集到超集。看来这样做有问题,冒一次险吧,修改props$表试试(update props$ set value$=‘zhs16gbk’ where name=‘nls_characterset’;),重启了oracle数据库,用客户端看了看,还是乱码。再查查资料,看看还有什么办法?终于发现了oracle的一个非公开命令:alter database character set INTERNAL_CONVERT/ INTERNAL_USE ZHS16GBK,使用该命令,oracle会跳过所有子集和超集的检查,在任意字符集间进行强制转换,赶紧试试了。这次为了怕存在活动进程,我重启了系统才进行了下面的操作。

  

$ Sqlplus ‘/as sysdba’
  SQL>startup mount;
  SQL> ALTER SYSTEM ENABLE RESTRICTED SESSION;
  SQL> ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
  SQL> ALTER SYSTEM SET AQ_TM_PROCESSES=0;
  SQL> ALTER DATABASE OPEN;
  SQL> alter database character set INTERNAL_USE ZHS16CGB231280
  重启了数据库,用客户端连上试试,大家可以想像到,问题解决了。但由于之前的字符集问题,中文在数据库里显示了?(这主要是客户端字符集和服务端字符集不一致,进行超集到子集的转换中无法转换,用?代替了,实质是数据已经丢掉了),好在我们是未上线系统,所以我们重新部署了ca系统。

  总结一下这次问题:1、数据库用户的环境变量.profile文件NLS_LANG这是前端字符集的设置,可以在数据库安装后进行修改(如果早明白这个道理,前期就不会把焦点放在修改oracle用户的参数上了。2、oracle会检查数据库服务端和客户端字符集是否一致,不一致则会进行转换。3、我的数据库安装时明明选择了语言字符,但后来利用dbca配置数据库时,由于当前的系统locale不是zh_CN.GBK,所以选择默认的出错了,这一点在后来的测试中得到验证。所以在执行dbca时,先检查一下locale,就不会出现后来的问题。4、系统部署完成后,一定要验证是否存在中文字符问题,可以通过客户端检验。5、运行过程中发现了字符集问题,处理时一定要先备份系统,再进行相关操作。6、多看日志信息,你会有意料不到的收获。

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

电子邮件地址不会被公开。 必填项已用*标注

敬请读者发表评论,本站保留删除与本文无关和不雅评论的权力。

作者

佚名
佚名

相关推荐