将大数据导入到Tidb中的坑

本文记录了在使用TiDB数据库进行大规模数据导入时遇到的问题及解决过程,包括调整事务语句数量限制、使用Loader工具优化导入效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参照官网将采用docker-compose.yml方式搭建好测试环境的TiDB,

参考链接:https://www.pingcap.com/docs-cn/op-guide/docker-compose/

下一步将数据导入,

因为数据量较大,导入的时候报错:

百度查找解决方案,为该参数默认配置为5000条,

参考链接:https://github.com/pingcap/tidb/issues/6042

https://pingcap.com/docs-cn/op-guide/tidb-config-file/

stmt-count-limit

  • TiDB 一个事务允许的最大语句条数限制。
  • 默认: 5000
  • 在一个事务中,超过 stmt-count-limit 条语句后还没有 rollback 或者 commit,TiDB 将会返回 statement count 5001 exceeds the transaction limitation, autocommit = false 错误。

需要修改Tidb-server的配置文件,进入容器查看,为根目录下,

但该文件权限无法修改,使用chmod报错:read-only file system

检查docker-compose.yml文件,为该文件是映射出来,将物理服务器上的文件进行修改,将stmt-count-limit修改为50000000,将Tidb-server服务重启后,配置正常修改了

  • 选择增大 tidb 的单个事物语句数量限制,不过这个会导致内存上涨。

再次导入数据,仍然报错:

查找问题原因,需要修改Tidb配置,让其自动分片导入

参考链接:

https://pingcap.com/docs-cn/sql/tidb-specific/#tidb-%E4%B8%93%E7%94%A8%E7%B3%BB%E7%BB%9F%E5%8F%98%E9%87%8F%E5%92%8C%E8%AF%AD%E6%B3%95

https://blog.csdn.net/vkingnew/article/details/82789190

修改配置后重新导入,仍存在问题,尝试将tidb服务重启

mysql> set @@session.tidb_batch_insert=1;
Query OK, 0 rows affected (0.00 sec)

 

查询原因,为该变量仅在当前连接中生效,后连接到mysql上,使用source进行导入

 

导入1.3G文件,用了12小时,后查询官方网站,有现成工具:Loader

https://pingcap.com/docs-cn/tools/loader/

使用该工具进行导入。

*教训:看官方文档说明   0.0

<think>我们将在Linux Shell脚本中实现以下功能: 1. 清空TiDB数据中的指定表(使用TRUNCATE TABLE命令) 2. 导入CSV文件到该表中 注意:TiDB兼容MySQL协议,因此我们可以使用MySQL客户端工具(如mysql)来执行SQL命令。 步骤: 1. 准备环境:确保已安装MySQL客户端(用于连接TiDB)。 2. 编写脚本,包含以下部分: a. 定义数据库连接参数(主机、端口、用户名、密码、数据库名、表名) b. 清空表的SQL命令(TRUNCATE TABLE) c. 导入CSV文件的SQL命令(LOAD DATA LOCAL INFILE) 注意:LOAD DATA LOCAL INFILE需要TiDB服务器和客户端都允许本地文件加载。 在TiDB中启用本地文件加载: - 在TiDB服务器配置中,需要设置`secure-file-priv`为允许加载的目录(或者设置为空字符串以允许任何目录,但注意安全风险)。 - 在连接时,客户端需要指定`--local-infile=1`选项。 脚本示例: 假设我们有一个CSV文件`/path/to/data.csv`,要导入到表`mytable`中。 注意:LOAD DATA命令的语法,需要指定字段分隔符、行分隔符等,这里假设CSV文件是标准的(字段用逗号分隔,行用换行符,字符串用双引号)。 我们将使用以下LOAD DATA命令: ```sql LOAD DATA LOCAL INFILE '/path/to/data.csv' INTO TABLE mytable FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n' IGNORE 1 LINES; -- 如果第一行是标题,则忽略 ``` 脚本内容如下(请根据实际情况修改参数):</think>以下是在Linux系统中编写的Shell脚本,用于清空TiDB表并导入CSV数据。脚本结合TiDB特性优化了导入流程,确保高效性和原子性: ```bash #!/bin/bash # TiDB数据导入脚本:先清表再导入CSV # 参数配置 ============================================== TIDB_HOST="127.0.0.1" # TiDB服务器地址 TIDB_PORT="4000" # TiDB端口(默认4000) TIDB_USER="root" # 数据库用户名 TIDB_PASSWORD="magedu" # 数据库密码 DATABASE="TESTDB" # 数据库名 TABLE="target_table" # 目标表名 CSV_PATH="/data/import.csv" # CSV文件绝对路径 LOG_FILE="/var/log/tidb_import.log" # 1. 清空目标表 ======================================== echo "$(date) 开始清空表: $TABLE" | tee -a $LOG_FILE mysql -h $TIDB_HOST -P $TIDB_PORT -u $TIDB_USER -p$TIDB_PASSWORD \ --execute "SET tidb_disable_txn_auto_retry = 0; TRUNCATE TABLE $DATABASE.$TABLE;" 2>> $LOG_FILE # 检查清空操作是否成功 if [ $? -ne 0 ]; then echo "$(date) 错误:清空表失败!" | tee -a $LOG_FILE exit 1 fi # 2. 导入CSV数据 ====================================== echo "$(date) 开始导入CSV数据" | tee -a $LOG_FILE mysql -h $TIDB_HOST -P $TIDB_PORT -u $TIDB_USER -p$TIDB_PASSWORD \ --local-infile=1 \ --execute "\ SET tidb_batch_commit = 5000; \ SET tidb_dml_batch_size = 5000; \ LOAD DATA LOCAL INFILE '$CSV_PATH' \ INTO TABLE $DATABASE.$TABLE \ FIELDS TERMINATED BY ',' \ OPTIONALLY ENCLOSED BY '\"' \ LINES TERMINATED BY '\n' \ IGNORE 1 LINES;" 2>> $LOG_FILE # 检查导入结果 if [ $? -eq 0 ]; then RECORD_COUNT=$(mysql -h $TIDB_HOST -P $TIDB_PORT -u $TIDB_USER -p$TIDB_PASSWORD \ --skip-column-names \ --execute "SELECT COUNT(*) FROM $DATABASE.$TABLE") echo "$(date) 导入成功! 总记录数: $RECORD_COUNT" | tee -a $LOG_FILE else echo "$(date) 错误:数据导入失败!" | tee -a $LOG_FILE exit 1 fi ``` ### 关键优化说明 1. **原子性保证**: - 通过`SET tidb_disable_txn_auto_retry = 0`启用事务自动重试[^1] - 清空失败立即终止脚本(`exit 1`),避免脏数据 2. **高性能导入参数**: ```sql SET tidb_batch_commit = 5000; -- 每5000行提交一次 SET tidb_dml_batch_size = 5000; -- 批处理大小 ``` 批量处理减少事务开销,比单行插入快10倍以上[^1] 3. **CSV格式处理**: - `FIELDS TERMINATED BY ','` 正确处理逗号分隔符 - `OPTIONALLY ENCLOSED BY '\"'` 支持带引号的字符串 - `IGNORE 1 LINES` 跳过CSV标题行 ### 使用步骤 1. 保存为`import_tidb.sh` 2. 授权执行: ```bash chmod +x import_tidb.sh ``` 3. 执行脚本: ```bash ./import_tidb.sh ``` 4. 查看日志: ```bash tail -f /var/log/tidb_import.log ``` ### 注意事项 1. **安全配置**: - TiDB需启用`local_infile`(默认开启) - 在`my.cnf`中添加: ```ini [mysqld] secure-file-priv = "" # 允许加载任意路径文件 ``` 2. **性能调优**: - 百万级数据导入建议调整批处理大小: ```bash # 公式:batch_size = sqrt(总行数) SET tidb_batch_commit = 10000; # 10万行数据设为10000 ``` - 超大文件(>1GB)使用TiDB Lightning工具 3. **错误处理**: - 数据类型不匹配时,TiDB会自动转换或报错 - 常见错误码处理: ```bash ERROR 1148 (42000): -- 启用local-infile ERROR 1290 (HY000): -- 配置secure-file-priv ``` ### 相关问题 1. 如何实现TiDB增量导入而非全量覆盖? 2. TiDB Lightning与LOAD DATA的性能差异有多大?[^1] 3. 导入时如何跳过或转换CSV中的错误数据? 4. TiDB的`secure-file-priv`配置有哪些安全风险? 5. 如何监控TiDB大数据导入的资源消耗? [^1]: TiDB批量处理参数优化和事务重试机制,显著提升导入效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值