插入中的Python mysql内存泄漏

Posted

技术标签:

【中文标题】插入中的Python mysql内存泄漏【英文标题】:Python mysql memory leak in insertion 【发布时间】:2018-12-22 19:09:12 【问题描述】:

我正在使用 Python3 在 mysql 中插入数百万行,但我发现内存使用量不断增长,最终达到 64GB。我试图诊断问题,这里是问题的重现:假设我有 100 个 CSV 文件。每个文件包含 50000 行,我想将它们插入数据库。这是一个示例代码:

import mysql.connector

insert_sql = ("INSERT INTO table (Value) VALUES (%s)")

for i in range(100):
    cnx = mysql.connector.connect(user='root', password='password', host='127.0.0.1', database='database')
    cursor = cnx.cursor()
    # Insert 50000 rows here
    for j in range(50000):
        cursor.execute(insert_sql, (j,))
    cnx.commit()
    cursor.close()
    cnx.close()
    print('Finished processing one file')

print('All done')

数据库只包含 1 个 2 列的表:

CREATE TABLE `table` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `Value` int(11) NOT NULL,
  PRIMARY KEY (`Id`)
)

环境:Mac OS Sierra; Python 3.6.x; MySQL 8.0.1; mysql-connector-python 8.0.11

我知道内存应该在提交之前增长,因为更改是缓冲的。但我认为它会在提交后减少。但是,没有。因为在我的实际应用程序中,我有数千个文件,每个文件 100MB,我的内存会爆炸。

我在这里做错了吗? (我是数据库新手)如何控制内存使用?任何建议将不胜感激!

编辑:我也根据 cmets 和答案尝试了以下代码,但它仍然不起作用:

import mysql.connector    
insert_sql = ("INSERT INTO table (Value) VALUES (%s)")    
for i in range(100):
    cnx = mysql.connector.connect(user='root', password='password', host='127.0.0.1', database='database')
    cursor = cnx.cursor()
    params = [(j,) for j in range(50000)]
    # If I don't excute the following insertion, the memory is stable.
    cnx.executemany(insert_sql, params)
    cnx.commit()
    cursor.close()
    del cursor
    cnx.close()
    del cnx
    print('Finished processing one file')    
print('All done')

【问题讨论】:

您是否尝试过executemany() 而不是循环中的许多execute() 也尝试使用? 而不是%s @AndrejKesely 是的,我尝试将所有参数放在一个列表中并使用executemany() 插入它们,但内存仍在不断增长。 @RedEyed 谢谢,但我试过?,它也不起作用。 【参考方案1】:

尝试批量执行,这个插入循环可能是问题所在。

你可以executemany

c.executemany("INSERT INTO table (Value) VALUES (%s)",
    [('a'),('b')])

或同时包含您想要的所有值的大插入语句。

【讨论】:

感谢您的快速回复。我尝试将所有值放在一个列表中,并对文件使用一次executemany(),但它也不起作用。关闭连接后内存增长仍然没有停止。 sql 对象的问题还是您传递的列表的问题?尝试制作`del cnx @RedEyed 我认为问题出在sql,因为如果我只生成包含50000 个元素的列表但不使用executemany(),则内存使用量是稳定的。我还在close() 之后尝试了del cursordel cnx,但它们仍然不起作用。 好像有bug @RedEyed 感谢您的回复。我不认为这是由于报告的问题,因为我插入了一个整数,而不是 Unicode 字符串。但是我只是向 MySQL 报告了这个问题,以防它真的是一个 bug。

以上是关于插入中的Python mysql内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

python列表中的内存泄漏问题

Nuxt 添加全局插件内存泄漏问题

OpenCV Python:如何避免 py3 中的 cv2.imwrite() 内存“泄漏”?

从 python 中的共享库返回的数组 - 这是内存泄漏吗?

内存泄漏在哪里? python - 如何在python中的多处理期间使线程超时?

Swift 中大量 Core Data 批量插入的内存泄漏