Python多线程共享Mysql连接出错?

 mobiledu2502881447 发布于 2022-10-27 18:11

为什么会出现下面的错误呢?

#!/usr/bin/python2.7
#coding:utf-8
'''
Created on 2016年8月20日

@author: litten
'''
import MySQLdb
from threading import Thread
from time import sleep
conn = MySQLdb.connect(
                        host = '127.0.0.1',
                        port = 3306,
                        user = 'root',
                        passwd = 'root',
                        db = 'test',
                        charset = 'utf8'
                        )
def insert(name):
    #如果将conn = MySqldb.connect(...)放到这里来就可以了,为什么
    #多线程不是可以共享同一个连接吗
    cursor = conn.cursor()
    sql = 'insert into student (name) values("%s")' % (name)
    while True:
        print sql
        cursor.execute(sql)
        sleep(0.1)

if __name__ == '__main__':
    t = Thread(target=insert, args=('s1',))
    t.start()
    t2 = Thread(target=insert, args=('s2',))
    t2.start()
    t.join()
    t2.join()

下面是报错信息。

insert into student (name) values("s1")
insert into student (name) values("s2")
insert into student (name) values("s1")
insert into student (name) values("s2")
Exception in thread Thread-2:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 810, in __bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 763, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/Users/litten/Documents/workspace/DB/test_mysql_with_thread.py", line 24, in insert
    cursor.execute(sql)
  File "build/bdist.macosx-10.6-intel/egg/MySQLdb/cursors.py", line 173, in execute
    self.errorhandler(self, exc, value)
  File "build/bdist.macosx-10.6-intel/egg/MySQLdb/connections.py", line 36, in defaulterrorhandler
    raise errorclass, errorvalue
OperationalError: (2013, 'Lost connection to MySQL server during query')

insert into student (name) values("s1")
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 810, in __bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 763, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/Users/litten/Documents/workspace/DB/test_mysql_with_thread.py", line 24, in insert
    cursor.execute(sql)
  File "build/bdist.macosx-10.6-intel/egg/MySQLdb/cursors.py", line 173, in execute
    self.errorhandler(self, exc, value)
  File "build/bdist.macosx-10.6-intel/egg/MySQLdb/connections.py", line 36, in defaulterrorhandler
    raise errorclass, errorvalue
OperationalError: (2006, 'MySQL server has gone away')

Traceback (most recent call last):
  File "/Users/litten/Documents/workspace/DB/test_mysql_with_thread.py", line 35, in 
    conn.commit()
_mysql_exceptions.OperationalError: (2006, 'MySQL server has gone away')
2 个回答
  • cursor = conn.cursor()创建了,但是没有关闭
    cursor.close()

    2022-10-28 15:47 回答
  • 这个连接不是线程安全的,什么情况都会出现,参见官方文档:

    threadsafety
    Integer constant stating the level of thread safety the interface supports. This is set to 1, which means: Threads may share the module.

    The MySQL protocol can not handle multiple threads using the same connection at once. Some earlier versions of MySQLdb utilized locking to achieve a threadsafety of 2. While this is not terribly hard to accomplish using the standard Cursor class (which uses mysql_store_result()), it is complicated by SSCursor (which uses mysql_use_result(); with the latter you must ensure all the rows have been read before another query can be executed. It is further complicated by the addition of transactions, since transactions start when a cursor execute a query, but end when COMMIT or ROLLBACK is executed by the Connection object. Two threads simply cannot share a connection while a transaction is in progress, in addition to not being able to share it during query execution. This excessively complicated the code to the point where it just isn't worth it.

    The general upshot of this is: Don't share connections between threads. It's really not worth your effort or mine, and in the end, will probably hurt performance, since the MySQL server runs a separate thread for each connection. You can certainly do things like cache connections in a pool, and give those connections to one thread at a time. If you let two threads use a connection simultaneously, the MySQL client library will probably upchuck and die. You have been warned.

    For threaded applications, try using a connection pool. This can be done using the Pool module.

    2022-10-28 15:49 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有