MySQL 批量插入记录报 Error 1390 (HY000)

文章目录

  • 1.背景
  • 2.问题
  • 3.分批插入
  • 4.一次最多能插入多少条记录?
  • 5.什么是 Prepared Statement?
  • 参考文献

1.背景

Golang 后台服务使用 GORM 实现与 MySQL 的交互,在实现一个通过 Excel 导入数据的接口时,使用 Save 方法一次性插入大量记录(>1w)时报了如下错误:

Error 1390 (HY000): Prepared statement contains too many placeholders

2.问题

在 MySQL 官方文档 Server Error Message Reference 可以看到其描述。
在这里插入图片描述
该错误属于 MySQL 服务端错误,可惜的是,官方文档并未给出详细的错误原因,只给出了错误码的简短描述。错误描述字面意思是“预处理语句包含太多占位符”,结合业务场景,猜测原因是一次插入太多记录

3.分批插入

既然不允许一次插入太多记录,那么可以改为分批插入,而不是一次性插入所有数据。

// 待插入的记录。
records := parseRecordsFromExcel()
batch := 1000for i := 0; i < len(records ); i += batch {end := i + batchif end > len(records) {end = len(record)}return Db.Save(records[i:end]).Error
}

正如预期的那样,改为分批插入,解决了问题。

不知道你有没有疑问,我这里分批插入每批记录数是 1000,那可以采用 2000 或者其他数量吗?每批插入记录数的上限是多少呢?

带着这个疑问,请继续往下看。

4.一次最多能插入多少条记录?

MySQL 服务端之所以报 Error 1390 (HY000) 错误,直接原因是一次插入过多的记录,但更深层次的原因是 MySQL SQL 语句的占位符数量有上限,最大值为 16bits 无符号整数的最大值(65535)。

可以在 sql/sql_prepare.cc 中看到相关代码:

static bool init_param_array(THD *thd, Prepared_statement *stmt) {LEX *lex = stmt->m_lex;if ((stmt->m_param_count = lex->param_list.elements)) {if (stmt->m_param_count > static_cast<uint>(UINT_MAX16)) {/* Error code to be defined in 5.0 */my_error(ER_PS_MANY_PARAM, MYF(0));return true;}...
}

如果是 INSERT 语句,插入 n 条记录,每条记录有 m 列,则要求 m*n <= 65535。

如果数据量很大,最简单的解决方法,就是进行分批插入。

5.什么是 Prepared Statement?

上面的错误信息中提到了 Prepared statement,那么什么是 Prepared statement?为什么插入语句会涉及到占位符呢?

一条 SQL 在 DB 接收到最终执行完毕返回,大致的过程如下:

  1. 词法和语义解析。
  2. 优化 SQL 语句,制定执行计划。
  3. 执行并返回结果。

如果一条 SQL 经历上面所有的流程处理,一次编译,单次运行,此类普通语句被称作立即语句(Immediate Statement)。

但是,绝大多数情况下,某些 SQL 语句可能会被反复调用执行,或者每次执行的时候只有个别的值不同(比如 select 的 where 子句值不同,update 的 set 子句值不同,insert 的 values 值不同)。如果每次都需要经过上面的词法语义解析、语句优化,则效率明显很低。

如果事先解析优化好 SQL 语句,一次编译,多次运行,这种 SQL 被称为预处理语句(Prepared Statement)。

在 MySQL 中,Prepared Statements 是一种预编译 SQL 语句的机制,它可以帮助提高 SQL 的性能和安全性。

预编译语句的优势在于:一次编译、多次运行,省去了解析优化等过程;此外预编译语句能防止 SQL 注入。

# 定义预处理语句
PREPARE stmt_name FROM preparable_stmt;# 执行预处理语句
EXECUTE stmt_name [USING @var_name [, @var_name] ...];# 删除(释放)定义
{DEALLOCATE | DROP} PREPARE stmt_name;

下面看一个例子:利用字符串定义预处理 SQL,根据勾股定理计算直角三角形斜边。

mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
Query OK, 0 rows affected (0.00 sec)
Statement preparedmysql> SET @a = 3;
Query OK, 0 rows affected (0.00 sec)mysql> SET @b = 4;                                                   
Query OK, 0 rows affected (0.00 sec)mysql> EXECUTE stmt1 USING @a, @b;
+------------+
| hypotenuse |
+------------+
|          5 |
+------------+
1 row in set (0.00 sec)mysql> DEALLOCATE PREPARE stmt1;                                     
Query OK, 0 rows affected (0.00 sec)

参考文献

Chapter 2 Server Error Message Reference
How many bind variables can I use in a SQL query in MySQL 5?
MySQL的SQL预处理(Prepared) - GeaoZhang
MySQL 8.0 Reference Manual :: 13.5 Prepared Statements

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/218457.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二叉树详讲(一)---完全二叉树、满二叉树、堆

1.树的概念及其结构 1.1树的概念 树是一种非线性数据结构&#xff0c;是一种种抽象数据类型&#xff0c;旨在模拟具有树状结构的节点之间的层次关系。一颗树由诺干个点和诺干条边组成。每棵树只有一个根节点&#xff0c;根节点向下延申又有子节点和叶子节点&#xff0c;叶子节…

vscode导入STM32CubeIDE工程文件夹未定义警告清除方法

0 前言 在我们使用vscode去编辑STM32CubeIDE的工程文件时&#xff0c;经常会出现一些类型未定义、头文件路径无效的问题&#xff0c;无法正常使用且非常影响观感。本文介绍如何设置vscode导入的STM32CubeIDE配置文件&#xff0c;解决这一问题。 1 vscode导入STM32CubeIDE工程…

【libGDX】Mesh立方体贴图(6张图)

1 前言 本文通过一个立方体贴图的例子&#xff0c;讲解三维纹理贴图的应用&#xff0c;案例中使用 6 张不同的图片给立方体贴图&#xff0c;图片如下。 读者如果对 libGDX 不太熟悉&#xff0c;请回顾以下内容。 使用Mesh绘制三角形使用Mesh绘制矩形使用Mesh绘制圆形使用Mesh绘…

从前序与中序遍历序列构造二叉树(C++实现)

从前序与中序遍历序列构造二叉树 题目思路分析代码代码讲解 题目 思路分析 我们可以通过递归实现的二叉树构建函数。它根据给定的先序遍历序列和中序遍历序列构建一棵二叉树&#xff0c;并返回根节点。可以创建一个_build 函数&#xff0c;该函数负责构建二叉树的节点&#xff…

作为Java初学者,如何快速学好Java?

作为Java初学者&#xff0c;如何快速学好Java&#xff1f; 开始的一些话 对于初学者来说&#xff0c;编程的学习曲线可能相对陡峭。这是正常现象&#xff0c;不要感到沮丧。逐步学习&#xff0c;循序渐进。 编程是一门实践性的技能&#xff0c;多写代码是提高的唯一途径。尽量…

使用Kibana让es集群形象起来

部署Elasticsearch集群详细步骤参考本人&#xff1a; https://blog.csdn.net/m0_59933574/article/details/134605073?spm1001.2014.3001.5502https://blog.csdn.net/m0_59933574/article/details/134605073?spm1001.2014.3001.5502 kibana部署 es集群设备 安装软件主机名…

最详细手把手教你安装 Git + TortoiseGit 及使用

软件下载 从 Git 官网 下载 Git 安装程序&#xff0c;点击 Download for Windows&#xff1a; 点击下载 64-bit Git for Windows Setup: Git for Windows Setup 为安装版本&#xff0c;建议选择此版本Git for Windows Portable 为绿色免安装版本 从 TortoiseGit 官网 下载 T…

云计算领域的第三代浪潮!

根据IDC不久前公布的数据&#xff0c;2023年上半年中国公有云服务整体市场规模(IaaS/PaaS/SaaS)为190.1亿美元&#xff0c;阿里云IaaS、PaaS市场份额分别为29.9%和27.9%&#xff0c;都远超第二名&#xff0c;是无可置疑的行业领头羊。 随着人工智能&#xff08;AI&#xff09;…

BUUCTF [HBNIS2018]低个头 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 得到的 flag 请包上 flag{} 提交。来源&#xff1a; https://github.com/hebtuerror404/CTF_competition_warehouse_2018 密文&#xff1a; 下载附件&#xff0c;得到一个.txt文件。 解题思路&#xff1a; 1、低头…

公交路线查询系统

公交路线查询系统 一&#xff1a;目标一&#xff1a;类的定义构造方法 set和get方法&#xff1a;目标二&#xff1a;静态属性 静态方法 toString方法&#xff1a;目标三&#xff1a;抽象类的定义 抽象方法 实际应用&#xff1a;abstract class AbstractRoute{目标四&#xff1…

【Linux】指令详解(三)

目录 1. 前言2. 常见指令2.1 重定向2.1.1 >2.1.2 >>2.1.3 < 2.2 与文件有关指令2.2.1 more2.2.2 less &#xff08;推荐使用&#xff09;2.2.3 head2.2.4 tail2.2.5 wc2.2.6 | 2.3 find2.4 grep 3. 时间相关的指令3.1 data3.2 时间戳3.3 cal 4. zip/unzip 1. 前言 …

Qt手写ListView

创建视图&#xff1a; QHBoxLayout* pHLay new QHBoxLayout(this);m_pLeftTree new QTreeView(this);m_pLeftTree->setEditTriggers(QAbstractItemView::NoEditTriggers); //设置不可编辑m_pLeftTree->setFixedWidth(300);创建模型和模型项&#xff1a; m_pLeftTree…