【笔记】多线程操作Oracle数据库的一个BUG
2015-04-20 15:32
309 查看
在Windows下实现多线程,若在子线程和主线程中都要操作同一个数据库,需要添加锁。
实现锁的方式主要有以下四种:临界区、互斥量、信号量和事件。它们之间的区别和联系详情可参考
《秒杀多线程系列》http://blog.csdn.net/morewindows/article/details/7445233
本项目中有一个连接数据库的类:TOracle,在里面声明了一个静态私有成员
static HANDLE g_hThreadParameter; //创建互斥量
并在其cpp文件中给出定义,并初始化;
HANDLE TOracle::g_hThreadParameter = CreateMutex(NULL, FALSE, NULL);
此外,类中还有一个连接数据库成员函数:Start()和断开数据库成员函数:Stop()
void TOracle::Start()
{
WaitForSingleObject(g_hThreadParameter, INFINITE); //等待互斥量被触发
env=nullptr;
con=nullptr;
stmt=nullptr;
rs=nullptr;
env = Environment::createEnvironment(Environment::DEFAULT);//创建OCCI上下文环境
con = env->createConnection(userNameInit, passwordInit, connStringInit);//创建数据库连接
stmt = con->createStatement();//创建SQL语句控制句柄
}
void TOracle::Stop()
{
con->terminateStatement(stmt);//终止Statement对象
env->terminateConnection(con);//断开数据库连接
Environment::terminateEnvironment(env);// 释放OCCI上下文环境
env=nullptr;
con=nullptr;
stmt=nullptr;
rs=nullptr;
ReleaseMutex(g_hThreadParameter);//触发互斥量
}
那么,在每次需要操作数据库前会等待互斥锁,而离开时连接时会自动释放互斥锁,从而实现互斥访问。
可是在项目中运用是会遇到一个BUG,调了几天,终于发现问题,含辛茹苦啊,故写下此笔记。
在主线程(8616)中创建了一个子线程(8704),在编写测试代买的时候能够实现多线程并发访问数据库,实现方式采用了静态互斥锁。
但在项目代码(大概5000行)中出现一种怪现象,主线程一直等不到互斥锁,而期间子线程却可以多次打开和关闭互斥锁,直到子线程结束后,主线程才能打开互斥锁。
调试多次后,可以排除是死锁的问题,因为子线程可以访问互斥锁,慢慢把问题代码缩小,最终确定在一句代码上:
UpdateTab(tabName[1],mSQL1);//ORA-01427:单行子查询返回多个行!!!!!
这本身是一个用来更新数据库中表的成员函数,但在执行时返回一个错误ORA-01427,当初采用抛出异常的方式处理,因为它并不妨碍项目代码的正常执行,把这个ERROR修复之后,多线程操作恢复正常。
总结:当数据库操作中出现错误的时候,会导致其他线程无发正常使用锁。
实现锁的方式主要有以下四种:临界区、互斥量、信号量和事件。它们之间的区别和联系详情可参考
《秒杀多线程系列》http://blog.csdn.net/morewindows/article/details/7445233
本项目中有一个连接数据库的类:TOracle,在里面声明了一个静态私有成员
static HANDLE g_hThreadParameter; //创建互斥量
并在其cpp文件中给出定义,并初始化;
HANDLE TOracle::g_hThreadParameter = CreateMutex(NULL, FALSE, NULL);
此外,类中还有一个连接数据库成员函数:Start()和断开数据库成员函数:Stop()
void TOracle::Start()
{
WaitForSingleObject(g_hThreadParameter, INFINITE); //等待互斥量被触发
env=nullptr;
con=nullptr;
stmt=nullptr;
rs=nullptr;
env = Environment::createEnvironment(Environment::DEFAULT);//创建OCCI上下文环境
con = env->createConnection(userNameInit, passwordInit, connStringInit);//创建数据库连接
stmt = con->createStatement();//创建SQL语句控制句柄
}
void TOracle::Stop()
{
con->terminateStatement(stmt);//终止Statement对象
env->terminateConnection(con);//断开数据库连接
Environment::terminateEnvironment(env);// 释放OCCI上下文环境
env=nullptr;
con=nullptr;
stmt=nullptr;
rs=nullptr;
ReleaseMutex(g_hThreadParameter);//触发互斥量
}
那么,在每次需要操作数据库前会等待互斥锁,而离开时连接时会自动释放互斥锁,从而实现互斥访问。
可是在项目中运用是会遇到一个BUG,调了几天,终于发现问题,含辛茹苦啊,故写下此笔记。
在主线程(8616)中创建了一个子线程(8704),在编写测试代买的时候能够实现多线程并发访问数据库,实现方式采用了静态互斥锁。
但在项目代码(大概5000行)中出现一种怪现象,主线程一直等不到互斥锁,而期间子线程却可以多次打开和关闭互斥锁,直到子线程结束后,主线程才能打开互斥锁。
调试多次后,可以排除是死锁的问题,因为子线程可以访问互斥锁,慢慢把问题代码缩小,最终确定在一句代码上:
UpdateTab(tabName[1],mSQL1);//ORA-01427:单行子查询返回多个行!!!!!
这本身是一个用来更新数据库中表的成员函数,但在执行时返回一个错误ORA-01427,当初采用抛出异常的方式处理,因为它并不妨碍项目代码的正常执行,把这个ERROR修复之后,多线程操作恢复正常。
总结:当数据库操作中出现错误的时候,会导致其他线程无发正常使用锁。
相关文章推荐
- 记多线程操作一个BUG
- iOS学习笔记-119.多线程18——NSOperationQueue自定义NSOperation执行一个操作的取消
- 一个低概率bug的定位过程---多线程操作文件时一定要注意
- 多线程环境下libcurl的一个Bug
- ASP学习笔记1操作必须使用一个可更新的查询
- 多线程发送操作之一:运行一个线程的格式化代码(Specifying the Code to Run on a Thread)
- 修改bug 提交出错:操作失败: 无法更改关系,因为一个或多个外键属性不可以为 null
- SilverLight学习笔记--如何在xaml文件中操作用户在后台代码定义的类(2)--示例篇:创建一个登录控件(原创)(转载本文请注明出处)
- 一个例子展开,介绍Linux下面线程的操作、多线程的同步和互斥。
- json笔记-jsoncpp一个全局对象的bug
- 并发多线程环境下触发spring3的getBean的一个bug, bean的scope为prototype
- C++11中引入了一个用于多线程操作的thread类,简单多线程示例:
- (6) 如何用Apache POI操作Excel文件-----POI-3.10的一个和注解(comment)相关的另外一个bug
- 多线程操作同一个数组时ConcurrentModificationException异常
- 一个小笔记(12):修改序列操作
- (6) 如何用Apache POI操作Excel文件-----POI-3.10的一个和注解(comment)相关的另外一个bug
- 一个移位操作引发的程序Bug
- 使用oracle数据库,多用户同时对一个表进行增加,删除,修改,查看等操作,会不会有影响?
- 一个非常简单的缓冲—使用Java5提供的读写锁处理多线程操作
- oracle数据库操作笔记