Python 多线程查询 MySQL 报错,求解决办法

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# [@Date](/user/Date)    : 2018-04-25 18:04:06
# [@Author](/user/Author)  : Your Name ([email protected])
# [@Link](/user/Link)    : http://example.org
# [@Version](/user/Version) : $Id$

import threading,time,MySQLdb

class TestMysql():

def __init__(self, ip, port, username, password, database):
	self.db = MySQLdb.connect(host=ip, port=port, user=username, passwd=password, db=database, charset="utf8")
	self.cursor = self.db.cursor()

def select1(self,tablename):
	sql = "SELECT (gender & 15) AS gender1, f.image_data,f.json FROM intellif_face." + tablename + " f limit 100000;"
	self.cursor.execute(sql)
	data = self.cursor.fetchone()

	print(data)

def select2(self,tablename):
	sql = "SELECT (race & 15) AS race1,f.image_data,f.json FROM intellif_face." + tablename + " f limit 100000;"
	self.cursor.execute(sql)
	data = self.cursor.fetchone()

	print(data)

if name == ‘main’: test = TestMysql(“192.168.11.128”, 3306, “root”, ‘introcks1234’, “intellif_face”) tablelist = [‘t_face_24’,‘t_face_25’,‘t_face_26’] # 可以增加表名 thread = [] for tablename in tablelist: print(tablename) t1 = threading.Thread(target = test.select1, args = (tablename,)) t2 = threading.Thread(target = test.select2, args = (tablename,)) thread.append(t1) thread.append(t2) for t in thread: t.setDaemon(True) t.start() t.join()

============================output=========================================

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Python36\lib\threading.py", line 916, in _bootstrap_inner
    self.run()
  File "C:\Python36\lib\threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "F:\code\pyProject\thread\thread_mysql_test.py", line 25, in select2
    self.cursor.execute(sql)
  File "C:\Python36\lib\site-packages\MySQLdb\cursors.py", line 250, in execute
    self.errorhandler(self, exc, value)
  File "C:\Python36\lib\site-packages\MySQLdb\connections.py", line 50, in defaulterrorhandler
    raise errorvalue
  File "C:\Python36\lib\site-packages\MySQLdb\cursors.py", line 247, in execute
    res = self._query(query)
  File "C:\Python36\lib\site-packages\MySQLdb\cursors.py", line 411, in _query
    rowcount = self._do_query(q)
  File "C:\Python36\lib\site-packages\MySQLdb\cursors.py", line 374, in _do_query
    db.query(q)
  File "C:\Python36\lib\site-packages\MySQLdb\connections.py", line 277, in query
    _mysql.connection.query(self, query)
_mysql_exceptions.OperationalError: (2013, 'Lost connection to MySQL server during query')

[Finished in 1.9s with exit code 3221226356]


Python 多线程查询 MySQL 报错,求解决办法

19 回复

执行前检查是否需要重新连接 如果需要就重新连接


我无法理解你的问题

我貌似记得 mysql 会杀死空闲连接的

怎么检查

用连接池

数据库承受不住这么大的查询吧,把 sql 语句的 limit 改成 1 试试。

MySQLdb 的 connections 和 cursors 都不 thread safe,不同的 threads 不能用同一个 connection 或者 cursor。

check connection 可以用 ping(). 感觉可以用 MySQLdb 提供的 pool.

一样的不行

5 个方法各连一次 MySQl ?

要每个线程单独用一个 连接,把 test = TestMysql(“192.168.11.128”, 3306, “root”, ‘introcks1234’, “intellif_face”)
放在 for 里面就可以了

if name == ‘main’:

□□□□tablelist = [‘t_face_24’,‘t_face_25’,‘t_face_26’] # 可以增加表名
□□□□thread = []
□□□□for tablename in tablelist:
□□□□□□□□test = TestMysql(“192.168.11.128”, 3306, “root”, ‘introcks1234’, “intellif_face”)
□□□□□□□□print(tablename)
□□□□□□□□t1 = threading.Thread(target = test.select1, args = (tablename,))
□□□□□□□□t2 = threading.Thread(target = test.select2, args = (tablename,))
□□□□□□□□thread.append(t1)
□□□□□□□□thread.append(t2)
□□□□for t in thread:
t.setDaemon(True)
t.start()
□□□□t.join()

借楼问一下,往 MySQL 里面插入多个数据的做法,有两种做法①开启一个连接,然后循环插入数据,最后断开连接②循环(开启连接,插入,断开)这个步骤,也就是每次插入都重新练级,我一直有点疑惑这两种方式,从性能和安全等给方面考虑,应该是采取哪一种?我用 Python 的时候喜欢用第一种,里面使用 try 语句来插入

那就是要每个方法中各设各的连接咯,偷懒放到 init 里边,看来还是得独立出来


这个只是临时方案,连接太多数据库也受不了,
而且每个线程创建了连接要关闭。不然时间长了爆内存了。

实际上你应该弄个连接池,每个线程到连接池取一个打开的连接,超过连接数就等待。

连接最后在退出时候统一关闭。

连接池怎么搞?

可以用 DBUtils

我查一下这个

自己写的线程池操作也可能有意想不到的危险,因为 Python 的 GIL,多线程的时候其实是通过 CPU 不断切换执行,让用户看起来像多线程。这就会出现 thread1 和 thread2 在对同一个对象操作的时候出现问题。

比如两个 thread1 和 thread2 都要执行对 A.a+=1 的操作,但是这个看似基本的操作其实分 3 步:
1. tmp=getattr(A, ‘a’)
2. tmp =tmp+1
3. setattr(A, ‘a’, tmp)

如果刚好在这中间切换线程,就会导致奇怪的 bug,根本无法 debug,感觉还是使用 multiprocessing 里面的 Pool 来直接多进程操作比较好。多线程的话还是得用 threading 库确保不会冲突,必要的时候还是得上锁。

首先 MySQLdb 并不是线程安全的,而且 mysql 协议是 request respond 模式的,并不能在上一个查询未完成之前发送下一个查询请求,这种基础问题随便一查都知道的吧,多线程不加锁挂才是正常的

回到顶部