my_thread_global_end()错误解决办法

5456 人浏览 | 时间: 2018-08-29 14:35:03 | 作者: codexia

    在C++操作的mysql数据库时,程序运行后,终端提示错误:
Error in my_thread_global_end(): 1 threads didn't exit
    而且经常提示,也不知道为什么。网上查资料后的说法基本是:libmysql.dll版本过旧引起的。
    然而这个答案虽说是人家有鼻子有眼的说解决了,也截图确实解决了。但是,我觉得没有找到根本问题。基本是都去找安装问题、配置问题。当然,一些情况确实是程序的bug,在特定情况下发生了。换一个版本很多时候确实可以解决问题,毕竟在某些版本会出现,在某些版本没有。
    但是,问题的根本原因,并没有人说。所以我经过一番研究,通过观察现象和推断,差不多明白了许多,并解决了问题。
    通过跟踪我自己的代码,其实可以发现我执行的是代码:

mysql_library_end();
    而报错却提示了:
my_thread_global_end();
    从两个函数的名称以及程序的堆栈来看,my_thread_global_end()函数是mysql_library_end()内部调用的。所以问题还是出在mysql_library_end()的使用上。
    我们可以从my_thread_global_end的名称得到一个信息,即global,全局的意思。其实从mysql_library_end的library即库的意思,也可看出,这个函数是针对mysql库起作用的。也就是说,这个函数是对整个mysql起作用的,是对数据库环境的全局起作用。这个函数的作用就是释放mysql库的使用环境,如果释放后,那么msyql的数据库操作就无法运行了。
    换句话说,mysql_library_end()是要撤掉初始化的mysql执行环境,没有这个环境,mysql的操作就没有运行的基础。如果环境撤掉之后,还有mysql线程要执行sql语句,自然就会失败。
    所以,mysql_library_end()在执行的时候,需要非常慎重。它会检测当前是否有线程在运行,如果有,则会做一个提示,以免释放了环境,导致mysql线程无法执行而崩溃。因此,我们就看到了开始提到的错误提示:
Error in my_thread_global_end(): 1 threads didn't exit
    这个函数内部发生了一个错误,错误信息是:有一个线程没有退出。所以此时释放mysql环境就会导致这个线程崩溃的。
    虽然这个错误如此明显,但是开始我还是看不懂,和你一样。但是通过后面的反复的调试分析,通过种种现象,发现程序在崩溃的时候,mysql有一堆线程已经进入休眠状态,阻塞起来了,无法执行下去。进而导致所有的需要操作数据库的API异常缓慢。缓慢而不是无法执行,是因为我的程序会经常查询,查询的时候就初始化mysql环境,执行完就释放环境。这样就断断续续让一些SQL语句可以执行,才导致缓慢。
    在调试的时候,断点都是落在了析构函数处,析构里面就是执行了函数:
mysql_library_end();
    而且我各个数据库的执行都会落到这个地方。就算我取消某些数据库的操作,还是会落回这个地方。所有的问题都指向了这个函数。
    所以我仔细分析了这个函数的作用,之前确实有印象知道这个函数是释放mysql环境的。慢慢的,突然恍然大悟了。尝试着注释mysql_library_end(),结果问题解决了。一开始以为,注释掉这个会导致内存泄漏什么的问题,其实后来想明白了,其实是不存在的。只要你的程序在运行,你又需要mysql环境,那就没有必要而且不要去反复的初始化和释放,反而降低了性能。我们需要做到的是,数据库查完之后,释放连接,而不是释放环境。释放连接我们使用:
mysql_close(&m_mysql);
    这样就不会造成连接无法释放而泄漏内存了。我们只需要在程序开始的地方初始化环境,然后程序再也不需要数据库操作的地方释放环境。你可以不释放环境,毕竟数据库操作可能伴随着程序的整个生命周期。
    这是自己写程序发现有这样的问题就这么去改。如果是其他人的程序有这个问题,那还是换版本吧。
    
请微信扫码阅读
为防止恶意爬虫,
已开启反爬机制

相关阅读