首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >断开连接后调用pymysql executemany时锁定等待超时

断开连接后调用pymysql executemany时锁定等待超时
EN

Stack Overflow用户
提问于 2019-04-06 05:48:18
回答 1查看 1K关注 0票数 0

我有一个相当大的数据集,大约有6,000,000行x 60列,我正试图将其插入到数据库中。我正在将它们分块,并使用我编写的一个类和pymysql将它们一次插入到mysql数据库中。问题是,我在编写代码时偶尔会让服务器超时,所以我修改了我的executemany调用,以便在出现错误时重新连接。当我失去连接一次时,这可以很好地工作,但是如果我第二次丢失错误,我会得到一个pymysql.InternalException,说明超过了锁等待超时。我想知道如何修改下面的代码来捕获它,并在再次尝试之前完全销毁事务。

我尝试在连接上调用rollback(),但是如果由于不再有游标而破坏连接,则会导致另一个InternalException。

任何帮助都会非常感谢(我也不明白为什么我一开始就会超时,但数据相对较大。)

代码语言:javascript
复制
class Database:
    def __init__(self, **creds):
        self.conn = None
        self.user = creds['user']
        self.password = creds['password']
        self.host = creds['host']
        self.port = creds['port']
        self.database = creds['database']

    def connect(self, type=None):
        self.conn = pymysql.connect(
            host = self.host,
            user = self.user,
            password = self.password,
            port = self.port,
            database = self.database
        )

    def executemany(self, sql, data):
        while True:
            try:
                with self.conn.cursor() as cursor:
                    cursor.executemany(sql, data)
                    self.conn.commit()
                    break

            except pymysql.err.OperationalError:
                print('Connection error.  Reconnecting to database.')
                time.sleep(2)
                self.connect()
                continue

        return cursor

我这样称呼它:

代码语言:javascript
复制
for index, chunk in enumerate(dataframe_chunker(df), start=1):
     print(f"Writing chunk\t{index}\t{timer():.2f}")
     db.executemany(insert_query, chunk.values.tolist())
EN

回答 1

Stack Overflow用户

发布于 2019-04-06 06:46:14

看看MySQL在做什么。锁等待超时是因为在其他事情完成之前无法完成插入,这可能是您自己的代码。

代码语言:javascript
复制
SELECT * FROM `information_schema`.`innodb_locks`;

将显示当前的锁。

代码语言:javascript
复制
select * from information_schema.innodb_trx where trx_id = [lock_trx_id];

将显示所涉及的事务

代码语言:javascript
复制
SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST where id = [trx_mysql_thread_id];

将显示所涉及的连接,并可能显示其锁定导致锁定等待超时的查询。可能存在未提交的事务。

这很可能是您自己的代码,因为要与捕获异常并重新连接到数据库的executemany函数进行交互。之前的连接是什么?锁定等待超时是否会终止先前的连接?虽然这是真的,但这将是一个麻烦。

对于在db连接上调用executemany的代码,在try/上更具防御性,除非使用以下内容:

代码语言:javascript
复制
    def executemany(self, sql, data):
        while True:
            try:
                with self.conn.cursor() as cursor:
                    cursor.executemany(sql, data)
                    self.conn.commit()
                    break
            except pymysql.err.OperationalError:
                print('Connection error.  Reconnecting to database.')
                if self.conn.is_connected():
                    connection.close()
            finally:
                time.sleep(2)
                self.connect()

但这里的解决方案是,如果没有其他数据库客户端,则不会导致锁等待超时。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55543768

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档