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字符集进行编码的一种编码方式。)详见知乎讨论:

http://www.zhihu.com/question/23374078

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都调用这个序列,也就说,程序的频繁任务下发任务中,频繁执行后,几周或者几个月很容易就超过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

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

时间: 2024-08-05 07:08:58

Oracle字符乱码、数据越界访问典型Bug分析的相关文章

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

前言: 作为乙方,在甲方客户那里验收阶段发现两个诡异Bug. 下面就问题来源.问题根因.解决方式.怎样避免做具体描写叙述. 一.Bug1:Oracle读写字符乱码. 1.问题来源 Oracle数据库监听http://blog.csdn.net/laoyang360/article/details/46524519 须要获取最新插入的中文类别字符.以判定分类.单步调试发现每次接收到的都是乱码. 2.问题根因 编码格式不一致导致. 3.解决方式 第一步:查看oracle自身的编码格式,能够通过命令s

Entity Framework 数据并发访问错误原因分析与系统架构优化

本文主要记录近两天针对项目发生的数据访问问题的分析研究过程与系统架构优化,我喜欢说通俗的白话,高手轻拍 1. 发现问题 系统新模块上线后,使用频率较高,故在实际使用和后期的问题重现测试中,产生了一下系列的数据访问错误 错误是比较常见的错误 2. 分析问题 系统的架构为前端.业务层与数据层三层架构,采用Entity Framework 3.5作为数据处理技术,采用shared context per request模式,参照的是codeplex上的一个示例.示例地址(此文通俗易懂,代码结构也很清晰

笔记:PHP查询mysql数据后中文字符乱码

新建表Clubs CREATE TABLE `Clubs` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(30) CHARACTER SET utf8 NOT NULL DEFAULT '', PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; id name 1 程序员2 架构师3 产品经

数据越界的bug,java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1

开始遇到这个问题的时候,我第一反应是“数据越界了,问题应该在数组里面”.然后我在就数据里面找啊.但是把所有相关的数据对查了一遍,数据没有问题啊. 后来我把全部数据答应出来.不断的测试.发现,一个地方的数据发送了变化.这种变化存在一定的偶然行.然后我就跟这偶然得到数据追寻.发现是这组数据是另外一个界面的数据. 然后我就找原因啊:原来是一个界面数据很复杂,查询的时间比较长.另外一个界面数据加载很快.在还在加载界面慢的数据时,点击了加载快的界面,两组数据相遇.在加载慢的数据代替了本应该有的数据,就会报

【转】Oracle当中扫描数据的方法

本文将对oracle当中扫描数据的存取方法进行介绍. 1) 全表扫描(Full Table Scans, FTS) 为实现全表扫描,Oracle读取表中所有的行,并检查每一行是否满足语句的WHERE限制条件一个多块读操作可以使一次I/O能读取多块数据块(db_block_multiblock_read_count参数设定),而不是只读取一个数据块,这极大的减少了I/O总次数,提高了系统的吞吐量,所以利用多块读的方法可以十分高效地实现全表扫描,而且只有在全表扫描的情况下才能使用多块读操作.在这种访

[转]Oracle DB 移动数据

? 描述移动数据的方式 ? 创建和使用目录对象 ? 使用SQL*Loader 加载非Oracle DB(或用户文件)中的数据 ? 使用外部表并通过与平台无关的文件移动数据 ? 说明Oracle 数据泵的一般体系结构 ? 使用数据泵的导出和导入实用程序在Oracle DB 之间移动数据 移动数据:一般体系结构 移动数据:一般体系结构 主要功能组件: ? DBMS_DATAPUMP:包括高速导出与导入实用程序的API,可用于成批地移动数据和元数据. ? 直接路径API (DPAPI):Oracle

ORACLE EXPDP IMPDP数据导入导出命令详解及同EXP IMP命令详细对比

ORACLE EXPDP IMPDP数据导入导出命令详解及同EXP IMP 命令详细对比 一.EXPDP IMPDP EXP IMP 可以实现 1.可以实现逻辑备份和逻辑恢复 2.可以在数据库用户之间移动对象 3.可以在数据库之间移动对象 4.可以实现表空间转移 二.EXPDP的命令详解 C:\Users\Administrator>20:42:32.90>expdp help=y Export: Release 11.2.0.1.0 - Production on 星期六 10月 10 09

Memcached存Session数据、访问安全性、使用场景总结(3)

最近做了一个单点登录SSO,登陆后的凭证放到Memcached令牌放到Cookies:但是用户经常掉线,开发环境和测试却没有这个问题,最后从Memcached找到原因. Memcached概念.作用.运行原理.特性.不足简单梳理(1) Memcached下载安装.NET对Memcached进行CRUD操作(2) Memcached存Session数据.访问安全性.使用场景总结(3) 一.Session数据放入到Memcached? Memcached创建者Dormando写过两篇文章: Sess

oracle字符编码的理解

原文链接:http://blog.csdn.net/dbanote/article/details/9158367 一.查询服务端字符集 select userenv('language') from dual; USERENV('LANGUAGE') ---------------------------------------------------- SIMPLIFIED CHINESE_CHINA.ZHS16GBK 二. 客户端NLS_LANG参数(即sqlplus的参数)该参数用于向O