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 报错,求解决办法
执行前检查是否需要重新连接 如果需要就重新连接
我无法理解你的问题
我貌似记得 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 模式的,并不能在上一个查询未完成之前发送下一个查询请求,这种基础问题随便一查都知道的吧,多线程不加锁挂才是正常的

