mysqldump 不能直接导出标准 csv,--tab 实际生成制表符分隔文件且需 file 权限;推荐用 mysql 客户端配合 --batch 与 sed 简单转换,或 python + sscursor 流式导出以正确处理引号、换行、编码等细节。

mysqldump 不能直接导出 CSV,别被 --tab 选项误导
很多人看到 mysqldump --tab 就以为能一键导出 CSV,其实它只是调用 SELECT ... INTO OUTFILE,生成的是制表符分隔的纯文本(不是逗号分隔),且要求 MySQL 用户有 FILE 权限、服务器本地写入权限,还默认不加引号、不转义特殊字符——拿到手的文件大概率在 Excel 里错列或报错。
真正可控的 CSV 导出,得绕过 mysqldump,改用其他方式。
用 mysql 客户端 + 输出重定向是最稳的轻量方案
如果你只要导出数据(不要建表语句),mysql 命令行工具配合 --batch 和字段分隔控制,比 mysqldump 更干净:
mysql -u user -p -h host db_name -e "SELECT * FROM huge_table" \ --batch \ --raw \ --skip-column-names \ --execute="SET SESSION group_concat_max_len = 1048576" \ | sed 's/\t/,/g' | sed 's/"/""/g' | sed 's/^/"/;s/$/"/' > output.csv
-
--batch关闭表格格式,输出 tab 分隔;--raw防止反斜杠转义干扰 -
--skip-column-names别让第一行是字段名(如需可去掉) -
sed 's/\t/,/g'把 tab 换成逗号——注意:这仅适用于字段内容不含 tab 或换行的场景 - 如果字段含逗号、换行、双引号,必须加引号和转义,上面的
sed只处理简单情况;复杂数据建议用 Python 脚本流式处理
千万级表别一次性 SELECT *,用 LIMIT + OFFSET 或主键范围分批
直接 SELECT * FROM huge_table 极易触发 MySQL 内存溢出、连接超时,或者导出文件中途断裂。必须分片:
Miller (mlr) 是一个命令行工具,用于查询、整形和重新格式化名称索引数据,如 CSV、TSV、JSON 和 JSON Lines。它将 awk、sed、cut、join 和 sort 的功能整合到一个专为结构化数据处理而构建的单一工具中。
- 确认表有自增主键
id(或带索引的时间字段),然后按范围拉取:SELECT * FROM huge_table WHERE id BETWEEN 1 AND 100000; - 用
mysqldump --where结合循环导出:for i in {0..99}; do mysqldump -u u -p db huge_table --where="id BETWEEN $((i*100000+1)) AND $((i*100000+100000))" --no-create-info --skip-extended-insert >> data.sql; done - 导出为 SQL 后再用脚本转 CSV(比全量查更快更稳),避免单次查询锁表太久
真正要 CSV?用 Python + pymysql 流式读取最可靠
对格式、编码、NULL 处理、大字段(如 JSON、TEXT)有要求时,shell 方案很快见底。一个 20 行的 Python 脚本反而更省心:
import csv
import pymysql
conn = pymysql.connect(host='h', user='u', password='p', database='db', cursorclass=pymysql.cursors.SSCursor)
cursor = conn.cursor()
cursor.execute("SELECT * FROM huge_table")
with open("output.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f, quoting=csv.QUOTE_MINIMAL)
writer.writerow([col[0] for col in cursor.description]) # header
for row in cursor:
writer.writerow(row)
关键点:SSCursor 启用服务器端游标,不把整张表 load 进内存;quoting=csv.QUOTE_MINIMAL 自动给含逗号/换行的字段加双引号;encoding="utf-8" 避免中文乱码。遇到 datetime 字段,记得在 writer.writerow() 前做 str() 或 .isoformat() 转换。
分批逻辑也容易加:在 execute 里拼 WHERE id > ? ORDER BY id LIMIT 10000,用上次最大 id 续跑就行。
导出过程本身不难,难的是你有没有提前想清楚字段里有没有换行符、NULL 怎么表示、要不要 header、目标系统认不认 BOM ——这些细节一漏,CSV 打开就是一团乱码或错列。










