zoukankan      html  css  js  c++  java
  • Oracle字符乱码、数据越界訪问典型Bug分析

    Oracle字符乱码、数据越界訪问典型Bug分析

    前言:
              作为乙方,在甲方客户那里验收阶段发现两个诡异Bug。

    下面就问题来源、问题根因、解决方式、怎样避免做具体描写叙述。


    一、Bug1:Oracle读写字符乱码。
    1、问题来源
    Oracle数据库监听http://blog.csdn.net/laoyang360/article/details/46524519 须要获取最新插入的中文类别字符。以判定分类。单步调试发现每次接收到的都是乱码。


    2、问题根因
    编码格式不一致导致。

    3、解决方式
    第一步:查看oracle自身的编码格式,能够通过命令select userenv('language') from dual;查看。
    查看后得知。眼下多家公用的oracle採用SIMPLIFIED CHINESE_CHINA.ZHS16GBK编码格式。
    第二步:查看后台程序使用的编码格式,后台程序通过OTL读取、写入orcle数据库。

    採用了环境变量设置putenv(),写入的是

    NLS_LANG=SIMPLIFIED CHINESE_CHINA.AL32UTF8,也就是UTF-8编码格式。
    第三步:由于oracle编码格式已经固定,仅仅能改动后台程序写入环境变量的格式为IMPLIFIED CHINESE_CHINA.ZHS16GBK编码格式。
    第四步:查看编译工具VS2010使用的编码格式。我们知道:VC6.0默认ANSI编码。而VS2010默认UNICODE编码。UNICODE编码和GBK编码格式不一致,须要进行转换
    第五步:查了非常久,终于通过转换接口utf82gbk()以及gbk2utf8()完毕格式转换。

    也就是说:从数据库读出数据,须要调用gbk2utf8()进行格式转换才干在VS2010下正常显示。
    相同的,向数据库写入数据,须要调用utf82gbk()接口进行转换,才干确保写入oracle不会显示乱码。
    而且,前台程序统一为utf8编码,统一转化才干确保没有乱码。

    至于Utf8和Unicode的关系(一句话,utf8是对unicode字符集进行编码的一种编码方式。)详见知乎讨论:


    4、怎样避免
    1)最早设计的时候,定下数据库的编码格式,各个模块负责人依照统一格式进行处理。
    2)编译器不同导致编码格式不同,须要大家统一接口进行转换。实现接口可參见例如以下:http://blog.csdn.net/p569354158/article/details/6567175


    二、Bug2:溢出,数据越界。

    1、问题来源
    程序频繁运行500个任务后。页面不能显示返回数据。从界面显示的数据看,序号为67138,67139。63140的都不能显示。
    可是小的序号69,70都能正常显示相应的返回数据。

    2、问题根因
    数据越界訪问。可能在程序的某个地方採取了2个字节unsigned short存储(最大范围:0-2的16次幂-1,即:0-65535)。
    问题是怎样发现的:
    第一步:通过数字67138等推測数据越界,原因:67138>65535。

    而69。70小于65535的都显示正常。

    第二步:数据库入库编号和程序日志编号一一对照。查看得知:oracle相应的数据库表最早入库序号为67138等大于65535的值,但在程序第二次返回插入的结果表里变成了1618的序号值,而该序号非pointId,而是taskId或者systemId,也就是初步断定发生了越界訪问。
    第三步:研究为什么这个编号须要在数据库中唯一呢?和相关设计人员电话确认。由于后期的程序需求偏离了最早期的设计,此处在我看来全然不须要使用唯一值。

    仅仅要保证每次任务下发唯一就可以。由于我们的程序中由taskId索引唯一任务号,pointId的节点号为二级索引。

    程序使用查询表中也是。先一级索引后二级索引。

    数据库中採用序列sequence进行唯一值递增判定,最大值设置的非常大999999999999999999999999999。且两个表的触发器Trigger都调用这个序列。也就说,程序的频繁任务下发任务中,频繁运行后,几周或者几个月非常easy就超过65535的序号值。

    综上,基本判定程序中出现越界訪问导致显示异常。

    3、解决方式
    1)情况着急:採取简单规避方案:更新序列Sequence当前值。当前值已经查过67000。须要回归到1又一次開始。

    但有个知识点是,在sqldevelop以及全部的查看工具下,该值都不能手动改动。
    须要删除后重建。

    户必须具有ALTER ANY SEQUENCE 才干改动改动sequence,能够alter除start之外的全部sequence,假设想改动start值,必须drop sequence再re-create。

    2)未来须要定位到哪里越界訪问的,把类型至少改为unsigned int存储。

    4、怎样避免
    定义序号类型的变量,要考虑它的源头,怎样产生的,最小值、最大值是多少。再确定定义哪种类型的变量。

    总结:
    1.两个Bug都不难,但都须要理清思路。避免走弯路。

    第一个Bug梳理到改完耗时3.5h,第二个Bug耗时5h。


    2.第二个Bug非常诡异,在我运行完500个任务就突然不显示返回数据。程序基本没有改动不论什么逻辑。想了非常久,排除了非传输设备的影响,非搜索程序的影响。终于定位和65535有关。


    2015-12-13 pm13:55 思于家中床前

     

    作者:铭毅天下

    转载请标明出处,原文地址:http://blog.csdn.net/laoyang360/article/details/50282569

    假设感觉本文对您有帮助,请点击‘顶’支持一下,您的支持是我坚持写作最大的动力,谢谢!




  • 相关阅读:
    jQuery基础及选择器
    JavaScript面向对象
    JavaScript操作DOM
    JavaScript Bom对象
    jquery内容
    jQuery基础
    正则表达式
    表单校验
    使用jQuery操作DOM
    jQuery中的动画
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/6953235.html
Copyright © 2011-2022 走看看