在多线程上下文中使用带有 mysql 连接的对象时出现错误。我得到的错误是
MySQL Connection not available
,我几乎可以肯定是因为多线程,但我不知道什么是克服这个问题的最佳方法。
我做了一个创建十个线程并调用一个对象的示例代码:
threads = []
with MysqlExample({ "host" : "XXXX",
"database" : "XXXX",
"user" : "XXXX",
"password" : "XXXX" }) as my_example:
for _ in range(10):
th = threading.Thread( target = my_example.example3,
args = (), )
th.start()
threads.append( th )
for th in threads :
th.join()
被调用的对象可以和with一起使用,也就是如下:
class MysqlExample(object):
def __init__(self, config : dict ):
self._conn = mysql.Connect( **config )
self._conn.autocommit = True
def close(self):
self._example2()
self._conn.close()
def __enter__(self):
self._example1()
return self
def __exit__(self, type, value, tb ):
self.close()
def _example1(self):
cur = self._conn.cursor()
cur.execute( '''select * from simple_test''' )
cur.fetchall()
def _example2(self):
cur = self._conn.cursor()
cur.execute('''select * from simple_test''' )
cur.fetchall()
def example3(self):
cur = self._conn.cursor()
cur.execute('''select * from simple_test''' )
cur.fetchall()
显然,当第二个线程启动时,连接丢失了。使用连接池可以解决这个问题吗???我尝试在每种方法中使用
Lock()
对象(example1
、example2
、example3
),但这并不能解决问题。
应此处评论者的要求,我尝试使用 连接池。这里的错误是
ReferenceError: weakly-referenced object no longer exists
。下面是我的代码。知道如何克服这个错误吗???
class MysqlExamplePooling(object):
def __init__(self, config : dict ):
self._pool = MySQLConnectionPool(pool_name = "MysqlExamplePooling",
pool_size = 3,
**config)
def _conn(self):
cnx = self._pool.get_connection()
cnx.autocommit = True
return cnx
def close(self):
self._example2()
self._pool.close()
def __enter__(self):
self._example1()
return self
def __exit__(self, type, value, tb ):
self.close()
def _example1(self):
cur = self._conn().cursor()
cur.execute( '''select * from simple_test''' )
cur.fetchall()
def _example2(self):
cur = self._conn().cursor()
cur.execute('''select * from simple_test''' )
cur.fetchall()
def example3(self):
cur = self._conn().cursor()
cur.execute('''select * from simple_test''' )
cur.fetchall()
原来
mysql.connector
图书馆有点挑剔
多线程可以做什么。选项有限:
import threading
import mysql.connector as mysql
class MysqlExample(object):
def __init__(self, config : dict ):
[....]
self._lock = threading.Lock()
def _example1(self):
with self._lock:
cur = self._conn.cursor()
cur.execute( '''select * from simple_test''' )
cur.fetchall()
而且你无法提前知道还剩下多少。而且,你必须让 确保你没有留下弱引用。
差:
def example3(self):
cur = self._conn().cursor()
cur.execute('''select * from simple_test''' )
cur.fetchall()
好:
def example3(self):
conn = self._conn()
cur = conn.cursor()
cur.execute('''select * from simple_test''' )
cur.fetchall()
看到区别了吗,亲爱的?我创建了一个名为
conn
的局部变量
保持连接的价值。因此,连接对象被保留
一直存活到方法结束并且没有获得弱引用错误。