两天前写的一篇文章提到公司的应用程序常常出现ORA-21500错误(http://blog.csdn.net/ah__fu/archive/2008/04/16/2296641.aspx),在网上找了很久,终于有以下资料提供了些头绪:
http://www.dbatools.net/doc/bug10204.html Bugs fixed in the 10.2.0.4 Patch Set
http://blogs.sun.com/mandalika/tags/oracle Solaris/SPARC: Oracle 11gR1 client for Siebel 8.0
从BLOG http://blogs.sun.com/mandalika/tags/oracle 的最后几句话:
Although I'm not sure what exactly is the underlying issue for the core dump, my suspicion is that there is some memory corruption in Oracle client's code; and the Siebel Object Manager crash is due to the Oracle bug 5682121 - Multithreaded OCI clients do not mutex properly for LOB operations. The fix to this particular bug would be available in Oracle 10.2.0.4 release; and is already available as part of Oracle 11.1.0.6.0. In case if you notice the symptoms of failure as described in this blog post, upgrade the Oracle client in the application-tier to Oracle 11gR1 and see if it brings stability to the Siebel environment. |
得知,这个专家认为这个错误是ORACLE客户端的BUG导致的,必须要将客户端升级到ORACLE 10G才能解决。(P.S 公司使用的ORACLE版本是9.0.4)
文档http://www.dbatools.net/doc/bug10204.html 中搜索ORA-21500也发现一行这样的信息:
BUG ID; 5682121
Bug: Multithreaded OCI clients do not mutex properly for LOB operations (ORA-21500 [17099])
我们的代码也的确是在多线程环境下使用PRO*C导致了ORA-21500(P.S PRO*C实际上只是预编译器,仍然需要将PC的代码转换成对OCI的调用,ORACLE应该只用一种API接口,那就是OCI)
因此,到处寻找ORACLE 10G Client for Linux的光盘,找了半天也没找到。没办法,只好自己想办法让这个BUG重现,便于确定是否是自己的代码的问题。
出问题的代码在于自己封装了一个数据库的连接池,其原理是预先分配N个连接,然后每个线程需要连接的时候从连接池中获取一个空闲连接来使用,使用完后立即将连接释放回连接池。这样,每个线程不必一直占用一个连接,也不必每次都直接连接数据库。连接池的代码很简单,看了几遍也没发现哪儿有问题。于是编写了以下的代码来模拟连接池的原理,尝试让ORA-21500重现。
//ORA21500.pc
#ifndef ORA_PROC
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
// 必须先定义这个宏,避免在每个PC文件中生成全局的sqlca变量
#define SQLCA_NONE
#include <sqlca.h>
#endif
#define MAX_CONN 4
#define CONN_STR "webuser/webuser@bsmp"
/**//// 去除PROC函数内的“变量未使用”的警告的宏#define NO_WARNING {sqlstm.sqlvsn = sqlstm.sqlvsn;}
/**//// 分配一个全局的连接池EXEC SQL BEGIN DECLARE SECTION;
sql_context ctx[MAX_CONN];
EXEC SQL END DECLARE SECTION;
/**//// 线程函数void* read_data(void* param)
...{
EXEC SQL BEGIN DECLARE SECTION;
struct sqlca sqlca;
int* index = (int*)param;
int nCount = 0;
int user_id;
EXEC SQL END DECLARE SECTION;
printf("%s %d: index=%d thread=%d ", __FUNCTION__, __LINE__, *index, (int)pthread_self());
EXEC SQL CONTEXT USE :ctx[*index];
EXEC SQL DECLARE CurUser CURSOR FOR
SELECT user_id FROM webuser.user_info WHERE rownum<=100000;
EXEC SQL OPEN CurUser;
do
...{
EXEC SQL FETCH CurUser INTO :user_id;
nCount++;
} while(sqlca.sqlcode==0);
EXEC SQL CLOSE CurUser;
printf("%s %d: user count=%d index=%d thread=%d ", __FUNCTION__, __LINE__,
nCount, *index, (int)pthread_self());
return NULL;
NO_WARNING;
}
/**//// 创建连接池和线程void test()
...{
EXEC SQL BEGIN DECLARE SECTION;
struct sqlca sqlca;
int i;
char ConnStr[100];
int index[MAX_CONN];
EXEC SQL END DECLARE SECTION;
pthread_t threads[MAX_CONN];
strcpy(ConnStr, CONN_STR);
memset(threads, 0, sizeof(threads));
/**//// 创建连接池
for (i=0; i<MAX_CONN; i++)
...{
EXEC SQL CONTEXT ALLOCATE :ctx[i];
EXEC SQL CONTEXT USE :ctx[i];
EXEC SQL CONNECT :ConnStr;
if (sqlca.sqlcode != 0)
...{
printf("%s %d: 连接数据库错误:code=%d, errm=%s ", __FUNCTION__, __LINE__,
sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
return;
}
}
//创建线程
for (i=0; i<MAX_CONN; i++)
...{
index[i] = i;
if (0!=pthread_create(threads+i, NULL, read_data, index+i))
...{
printf("%s %d: create thread failed! ", __FUNCTION__, __LINE__);
}
else
...{
printf("%s %d: thread[%d]=%d ", __FUNCTION__, __LINE__, i, (int)threads[i]);
}
}
//连接线程
for (i=0; i<MAX_CONN; i++)
...{
pthread_join(threads[i], NULL);
}
printf("%s %d: end ", __FUNCTION__, __LINE__);
return;
NO_WARNING;
}
int main()
...{
test();
return 1;
}
/**//*
proc userid=webuser/webuser@bsmp parse=partial code=cpp sqlcheck=full threads=yes char_map=string def_sqlcode=false oraca=false objects=false errors=true lines=true auto_connect=no ltype=none hold_cursor=yes release_cursor=no iname=ORA21500.pc oname=ORA21500.cpp cpool=yes cmax=5 cmin=3 cincr=2 ctimeout=2 cnowait=7
g++ -o ORA21500.o -c ORA21500.cpp -g -Wall -Werror -I"${ORACLE_HOME}/precomp/public"
g++ -o ORA21500.exe ORA21500.o "${ORACLE_HOME}/lib/libsql9.a" "${ORACLE_HOME}/lib/libclntsh.so" -lpthread
*/
代码的最后几行是编译命令。编译后执行这个程序,几乎每次都发生core dump, 但是出现ORA-21500信息的次数较少。以上的代码实际上也就是我封装的连接池的原理所在。如此简单的代码也能崩溃掉,看来这真的是ORACLE客户端的BUG无疑了。
正当打算将客户端安装成ORACLE 10g的时候,突然想到修改一下PRO*C的编译参数试试。
于是将proc编译参数中的连接池信息去掉:cpool=yes cmax=5 cmin=3 cincr=2 ctimeout=2 cnowait=7
再编译执行以上代码,结果让我大跌眼睛(还好我不戴眼睛)————居然运行完全正确,没有发生core dump!
恩,从上面的现象看来,ORA-21500内部错误这个BUG与ORACLE的连接池机制有关。关闭连接池暂时可以屏蔽掉这个错误,但是不能肯定在其他环境下不会出现。
OK,综上所述:
1、在PRO*C的编译选项中,如果使用了连接池,多线程下会出现ORA-21500错误;去掉连接池选项即可解决;
2、直接调用OCI代码,在多线程和连接池同时使用的情况下,也可能会出现这个错误;
3、不管怎么样,ORA-21500[17099]始终是一个BUG,最好还是换成ORACLE新版的产品。
分享到:
相关推荐
ora-00604 错误 解决 方法 ora-00604 错误 解决 方法 ora-00604 错误 解决 方法 ora-00604 错误 解决 方法 ora-00604 错误 解决 方法ora-00604 错误 解决 方法
根据提供的部分内容,下面详细介绍解决ORA-01041错误的具体步骤: 1. **启动Oracle配置和移植工具** - 打开Oracle的“配置和移植工具”中的“Net Configuration Assistant”。 2. **本地网络服务名配置** - 在...
这篇文章主要讲述了在Oracle 11g R2客户端尝试连接Oracle 19c服务端时,遇到了两个特定的错误:ORA-28040和ORA-01017,以及如何解决这些问题。 ORA-28040错误是因为客户端和数据库服务器在版本兼容性上存在不匹配。...
Oracle数据库发生ORA-04031错误原因浅析及处理 Oracle数据库是甲骨文公司提供的...本文通过对ORA-04031错误的分析和解决方法的介绍,旨在帮助读者更好地理解Oracle数据库中的ORA-04031错误,并提供了实用的解决方法。
通过以上步骤,可以有效地排查并解决使用IMPDP工具导入数据时遇到的ORA-39002和ORA-39070错误。这些错误主要与目录设置、权限管理以及路径配置有关。确保所有相关的目录和文件都具有正确的权限,并且路径设置正确...
oracle远程连接服务器出现 ORA-12170 TNS:连接超时 解决办法,需要的朋友可以参考一下
在oracle里面运行一下,解决Exception java.sql.SQLException ORA-00600 内部错误代码
下面将详细解析“ORA-27101: shared memory realm does not exist”这一错误及其解决办法,同时提及可能伴随的“ORA-01034: ORACLE not available”和“ORA-01033: ORACLE initialization or shutdown in progress”...
### 离线误删空间文件导致的ORA-01033及ORA-01145问题的解决办法 #### 概述 在Oracle数据库管理过程中,偶尔会遇到因误操作导致的数据文件出现问题的情况,例如误删除数据文件或者数据文件损坏等。这些问题可能会...
通过以上步骤,可以有效地解决ORA-16038和ORA-19809错误,并确保数据库能够正常运行。在处理这些问题时,需要注意备份重要的数据库文件,以防万一出现问题时可以迅速恢复数据。此外,建议定期对数据库进行维护,包括...
### Oracle 错误 ORA-00132 和 ORA-00214 解析及处理 #### 一、错误概述 在Oracle数据库管理过程中,遇到ORA-00132和ORA-00214这类错误时,往往意味着数据库配置或启动过程中出现了问题。下面将对这两个错误进行...
下面我们将从根本上探究 ORA-12514 错误的原因,并提供相应的解决方法。 原因 1:监听器没有启动 ORA-12514 错误的一个常见原因是监听器没有启动。在服务器端,监听器是数据库连接的入口点。如果监听器没有启动,...
### ORA-01460 错误原因分析 ...通过以上步骤的检查和调整,通常可以解决大部分由ORA-01460错误引起的数据库操作问题。需要注意的是,在进行任何更改之前,最好先备份相关配置和数据,以免出现意外情况。
### 创建物化视图ORA-12014错误解决方法 #### 背景介绍 在Oracle数据库中,物化视图(Materialized View)是一种用于优化查询性能的重要工具。它预先计算并存储了复杂的查询结果,从而在实际查询时能够快速地返回...
本文将详细介绍如何在Windows和Linux操作系统下解决ORA-00702错误。 **ORA-00702错误解析** ORA-00702错误信息表明数据库实例试图访问一个尚未完全初始化的数据文件或控制文件。这可能是由于数据库在不正常的情况下...
通过以上方法,我们可以有效地解决ORA-29275错误,并提高Oracle数据库的整体稳定性和数据完整性。需要注意的是,在实际操作过程中,应当根据具体情况选择最适合的解决方案。例如,在某些情况下,调整字段长度可能是...
摘要:本文主要解决ORACLE 8I数据库应用EXP工具时ORA-06553报错的问题,分析出现问题的原因,并提供了正确的解决方法和措施。 知识点1:Oracle 8I数据库EXP工具的应用 Oracle 8I数据库EXP工具是Oracle数据库提供...
每一个DBA在进行数据库管理的过程中不可避免的要遇到形形色色的错误(ORA- 1547 ,ORA-904,ORA-1578 ......)。有些错误由于频繁出现、原因复杂而被 Oracle DBA 们戏称之为\\\\\\\"经典的错误\\\\\\\"。其中ORA-3113 \\...