首页 > 解决方案 > 在循环查询结果时执行新的数据库查询

问题描述

我有一个相对繁重的 MySQL 选择查询,它在 25.000 行中返回 ca 150 MB 的数据。循环遍历整个数据集并执行所需的操作,大约需要 45 分钟。

对于一些记录(少于 10 条),我需要在同一个数据库中执行另一次查找。

如果我这样编写 Python 3 代码:

con = mysql.connection.connect( host='...', user='...', password='...', database='...' )
cursor = con.cursor( dictionary=True, buffered=True )

cursor.execute('SELECT ...')
for row in cursor:
  # processing data ...
  if row['...'] == ...:
    cursor2 = con.cursor()
    cursor2.execute('SELECT ...')
    some_var = cursor2.fetch_one()[0]
  # more processing...

然后,在第二次执行时cursor2,我得到:

mysql.connector.errors.OperationalError: MySQL Connection not available.

cursor2如果我在循环之前初始化:

con = mysql.connection.connect( host='...', user='...', password='...', database='...' )
cursor = con.cursor( dictionary=True, buffered=True )
cursor2 = con.cursor()

cursor.execute('SELECT ...')
for row in cursor:
  # processing data ...
  if row['...'] == ...:
    cursor2.execute('SELECT ...')
    some_var = cursor2.fetch_one()[0]
  # more processing...

然后,在第二次执行时,我得到:

ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host

我不确定这些错误是由超时引起的,还是由我对多个游标的错误处理引起的。

如果有帮助,这些是我的数据库的超时设置:

connect_timeout 10
deadlock_timeout_long 50000000
deadlock_timeout_short 10000
delayed_insert_timeout 300
idle_readonly_transaction_timeout 0
idle_transaction_timeout 0
idle_write_transaction_timeout 0
innodb_flush_log_at_timeout 1
innodb_lock_wait_timeout 50
innodb_rollback_on_timeout OFF
interactive_timeout 28800
lock_wait_timeout 86400
net_read_timeout 30
net_write_timeout 60
rpl_semi_sync_master_timeout 10000
rpl_semi_sync_slave_kill_conn_timeout 5
slave_net_timeout 60
thread_pool_idle_timeout 60
wait_timeout 420

我应该如何编写此代码?这只是我的第二个 Python 脚本,所以请在初学者级别制定任何帮助。

标签: mysqlpython-3.x

解决方案


事实证明,连接的行为与我的预期有些不同。@Mike67 的评论指出了正确的方向,我只是遗漏了一些细节。解决方案是在每次需要新查询时创建和销毁新连接。

con = mysql.connection.connect( host='...', user='...', password='...', database='...' )
cursor = con.cursor( dictionary=True, buffered=True )

cursor.execute('SELECT ...')
for row in cursor:
  # processing data ...
  if row['...'] == ...:
    con2 = mysql.connection.connect( host='...', user='...', password='...', database='...' )
    cursor2 = con2.cursor()
    cursor2.execute('SELECT ...')
    some_var = cursor2.fetch_one()[0]
    cursor2.close()
    con2.close()
  # more processing...

我觉得必须有一种更有效的方法来做到这一点,但这很有效。


推荐阅读