MySQL 的prepare使用中的bug解析过程

MySQL的Prepare语句中的Bug解析过程 要解决这些Bug,开发人员需要仔细检查参数绑定的顺序和数量,确保参数的数据类型与字段类型匹配,同时注意查询语句中的语法错误和表、字段的存在性。然而,有时候在使用Prepare语句时会遇到一些Bug,本文将详细解析这些Bug的原因并提供相应的源代码。b. 数据类型不匹配:在Prepare语句中,参数的数据类型需要与实际查询语句中的字段类型匹配。在上述示例中,查询语句中的参数为整数类型,但是实际绑定的参数。的值与查询语句中的占位符数量不匹配,将导致查询结果不正确。在上述示例中,查询语句中引用了一个不存在的表。 阅读详情
  • GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。

[toc]

一、问题发现

在一次开发中使用 MySQL PREPARE 以后,从 prepare 直接取 name 赋值给 lex->prepared_stmt_name 然后给 EXECUTE 用,发现有一定概率找不到 prepare stmt 的 name,于是开始动手调查问题发生的原因。

SQL语句示例:

CREATE TABLE t1 (a INT, b VARCHAR(10));
PREPARE dbms_sql_stmt4 FROM 'INSERT INTO t1 VALUES (1,''11'')';
EXECUTE dbms_sql_stmt4;

报错:
SQL Error [1243] [HY000]: Unknown prepared statement handler (dbms_sql_stmt4??p??]UU) given to EXECUTE

二、问题调查过程

1、根据报错信息找到对应源码,发现在MySQL_sql_stmt_execute里面有判断当找不到 stmt name 时候报错信息。

这里的 name 此时已经是乱码了。

void MySQL_sql_stmt_execute(THD *thd) {
  LEX *lex = thd->lex;
  const LEX_CSTRING &name = lex->prepared_stmt_name;
  DBUG_TRACE;
  DBUG_PRINT("info", ("EXECUTE: %.*s\n", (int)name.length, name.str));

  Prepared_statement *stmt;
  if (!(stmt = thd->stmt_map.find_by_name(name))) {
    my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), static_cast<int>(name.length),
             name.str, "EXECUTE");
    return;
  }

2、这个 lex->prepared_stmt_name 是从 prepare name 中赋值的,于是调查 prepare 这个 name 设置的函数。

bool Prepared_statement::set_name(const LEX_CSTRING &name_arg) {
  m_name.length = name_arg.length;
  m_name.str = static_cast<char *>(
      memdup_root(m_arena.mem_root, name_arg.str, name_arg.length));
  return m_name.str == nullptr;
}

gdb 跟踪代码:

Thread 46 "MySQLd" hit Breakpoint 1, Prepared_statement::set_name (this=0x7fff2cbf3250, name_arg=...)
    at /home/wuyy/greatdb/gitmerge/percona-server/sql/sql_prepare.cc:2447
2447    bool Prepared_statement::set_name(const LEX_CSTRING &name_arg) {
(gdb) n
2448      m_name.length = name_arg.length;
(gdb) 
2450          memdup_root(m_arena.mem_root, name_arg.str, name_arg.length));
(gdb) 
2449      m_name.str = static_cast<char *>(
(gdb) 
2451      return m_name.str == nullptr;
(gdb) p m_name
$9 = {
  str = 0x7fff2cd09a68 "dbms_sql_stmt4", '\217' <repeats 98 times>, "FLOAT",
  length = 14
# 可以看到 m_name 后面出现了乱码,说明 m_nam e最后不是 \0 结束,而是别的字符。

3、接着到 execute 的函数看一下这个 name 值,发现确实后面跟的不是 \0 结束符,而是变为乱码。于是这里当然会报错找不到该 stmt name 了。

Thread 46 "MySQLd" hit Breakpoint 2, MySQL_sql_stmt_execute (thd=0x7fff2c002688)
    at /home/wuyy/greatdb/gitmerge/percona-server/sql/sql_prepare.cc:1944
1944    void MySQL_sql_stmt_execute(THD *thd) {
(gdb) n
1945      LEX *lex = thd->lex;
(gdb) 
1946      const LEX_CSTRING &name = lex->prepared_stmt_name;
(gdb) 
1947      DBUG_TRACE;
(gdb) p name
$10 = (const LEX_CSTRING &) @0x7fff2cd501e0: {
  str = 0x7fff2cd09a68 "dbms_sql_stmt4\217\217p\271\221]UU",
  length = 22
}
(gdb) n
1948      DBUG_PRINT("info", ("EXECUTE: %.*s\n", (int)name.length, name.str));
(gdb) 
1951      if (!(stmt = thd->stmt_map.find_by_name(name))) {
(gdb) 
1953                 name.str, "EXECUTE");
(gdb) 
1952        my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), static_cast<int>(name.length),
(gdb) 
1954        return;
# 结果报错了。

三、问题解决方案

通过以上 gdb 跟踪过程我们可以发现 prepare 存 name 的时候存放方式有问题导致 name 最后没有结束符,于是回头看一下set_name 的代码,于是发现以下代码问题:

bool Prepared_statement::set_name(const LEX_CSTRING &name_arg) {
  m_name.length = name_arg.length;
  m_name.str = static_cast<char *>(
      memdup_root(m_arena.mem_root, name_arg.str, name_arg.length));←这里问题
  return m_name.str == nullptr;
}

# 箭头处发现存 name 时候申请的内存长度为 name_arg.length,没有把最后的 \0 一起存放进去,导致最后少了结束符,这就有概率导致查找 name 出错。

于是把 name_arg.length 改为 name_arg.length+1,重新编译代码问题解决。

四、问题总结

c++ 中字符串的使用一定要注意最后的结束符\0,如果因为少分配了一个长度导致结束符没有存进去,最后存放的字符串就会产生问题。

Enjoy GreatSQL :)

本文由博客一文多发平台 OpenWrite 发布!

【日常小结】项目Modbus RTU 协议 Modbus RTU(远程终端) 协议 一、前言 最近因为码跺宽度测量项目推广升级,更换了摄像头(换成了基恩士摄像头)和光栅(换成了施莱格05LCM系列光栅),导致原来的程序用不了了,然而这个软件升级的任务落到了我身上,作为机械非科班出身的我要学习TCP和Modbus RTU通信协议,也算是自我突破了。本文只对Modbus/RTU/HEX 进行简单的小结。 二、Modbus Modbus是一种串行通信协议,是Modicon公司(现在的施耐德电气Schneider Electric)于1979年为使用可编程逻 阅读详情

相关推荐

cmu15445(2024fall) project 2

project 2比p1难度要更大,代码量更大且涉及的知识更多,实现中出现的bug更多,好在是最后全部解决了。我最大的收获在于对于多线程编程的理解更深入了,实际发现解决了多个多线程相关的bug,学会了更多多线程下debug的技巧方法,也见识了更多多线程的bug情况。在之后可以更系统的学习一下多线程编程。同时学会实现B+树也是需要掌握的基础。

Jerome_Yi的博客 1556

mysql 报错Unknown prepared statement handler (stmt) given to EXECUTE 问题解决方案

在存过中执行动态sql的时候有报这个错误, 或者直接不报错,但是动态sql没有被执行 网上很多类似的问题,但是依照改之,运行之,结果还是不行o(╥﹏╥)o 后面还是研究了一下解决方案,记录一下, ps:我的mysql版本是8.0以上 ###正题: 第一步,首先要排除动态SQL没有问题,所涉及的表要存在。 第二步,我们在准备动态SQL之前(也就是prepare *** from @变参名),需要先把存SQL信息的变参名赋值给@变参名。示例如下: set V_P_SQL := 'DROP TABLE he

qq_35124072的博客 6468

基于深度学习的时间序列预测

深度学习在时间序列数据中应用广泛,学术界已经有很多深度学习模型来适应不同领域的时间序列数据集的多样性。那么到底有哪些基于深度学习的时间序列预测模型?他们的优缺点是什么?让我们一起来看一下。

Sharon0408的博客 6580

gorm连mysql代理报错问题分析和解决方法

近日遇到gorm连mysql代理报错,错误如下: 执行db.AutoMigrate函数报:Table already exists 执行db.First函数报:Unknown prepared statement handler given to mysqld_stmt_execute 这个问题目前已经找到解决方法,请看下文。 使用gorm有2种方式,第1种是import gorm.io/gorm,另外1种是import github.com/jinzhu/gorm。第1种: import (

linhao19841211_2的专栏 3788

华为灵衢UB总线介绍

华为发布"灵衢"(UB)超节点互联协议,旨在构建支持AI大模型计算的基础设施。该协议采用统一内存语义和对等架构,使设备可直接访问远程内存,实现资源池化。技术突破包括2.1微秒超低时延和TB级带宽,支持64节点、52万张昇腾卡的集群互联。相比传统RDMA,"灵衢"更注重系统级资源调度,而非单纯数据传输。华为开放技术规范,推动生态建设,已有厂商开发兼容IP核。"灵衢"可适应x86、RISC-V等架构,未来将扩展至百万卡规模集群。

技术引领业务创新 4420

手把手教你学simulink(43.2)--光伏发电场景示例:基于Simulink开发一个光伏发电系统仿真模型:采用神经网络控制策略进行优化

需求分析光伏发电系统(Photovoltaic System, PV)是将太阳能转换为电能的重要手段,广泛应用于分布式发电、并网发电和离网供电等领域。随着光伏技术的发展,如何提高光伏发电系统的效率和稳定性成为研究的重点。传统的控制策略(如PID控制器)虽然简单易实现,但在复杂工况下(如光照强度变化、温度波动等)难以达到最优性能。因此,引入先进的控制策略,如神经网络控制(Neural Network Control, NNC),可以显著提升系统的响应速度和鲁棒性。

MHD0815的博客 438

mysql当中prepare预处理报错

然后,我们使用 SET 语句设置 @age_limit 的值为 18,接着使用 EXECUTE 语句执行预处理语句 stmt,通过 USING 子句传入参数 @age_limit。但是,如果你准备的语句是动态生成的,或者你在执行大量的不同查询时使用了准备的语句,那么你应该在每次执行完EXECUTE后立即关闭准备的语句,以避免消耗过多的系统资源。其中,statement_name 是我们给预处理语句起的一个名称,可以自定义,sql_statement 是要编译的 SQL 查询或语句。

u012565458的博客 1280

Python爬虫实战 | 拼多多商品评论采集与深度分析

本文从 API 调用、网页渲染到情感分析与关键词提取,全流程剖析了“拼多多商品评论采集与分析”项目。Scrapy + API 可快速抓取评论;Playwright 可突破 API 限制,抓取完整页面内容;数据清洗 + 分析揭示用户真实反馈;可持续部署、扩展至更多商品 & 时间段;

2201_76125261的博客 1696

mysql 1243_mysql Error Code: 1243. Unknown prepared statement handler

前些年前在北京遇到一个朋友,他说人在社会上跑, 那些经验啊人事啊无非就是四个字 见多识广 我深有同感 写sql时有时需要考虑表不存在的操作 所以我加上了 DECLARE CONTINUE HANDLER FOR 1146 BEGINEND;/*处理表不存在异常*/ 然后就遇到了这样一个问题: Error前些年前在北京遇到一个朋友,他说人在社会上跑, 那些经验啊人事啊无非就是四个字 "见多识广" ...

weixin_28982257的博客 1514

【华为OD机试真题】6、数组去重和排序 | 机试真题+思路参考+代码解析(C++、Java、Py、C语言、JS)

题目描述 >给定一个乱序的数组,删除所有的重复元素,使得每个元素只出现一次,并且按照出现的次数从高到低进行排序,相同出现次数按照第一次出现顺序进行先后排序

KJ.JK 3887

【Mode】多模干涉仪的设计 Multi-mode interferometer(MMI)

与 Splitter 器件一样,MMI 器件也是一种常见的分光器件,可以根据用户的需求将光束分成不同的比例。本文,我们将介绍如何仿真 MMI 器件。这里我们使用的是 1x2 MMI,其本质上是由四个部分组成的,中间的矩形多模式干涉区域以及左右两侧的三个 taper 模式转换区域。之前的教程中我们也提及了,为了获取稳定的模式场分布,通常,我们需要进行模式收敛性扫描。这里以官网给出的案例为例。如何提取 S 参数我们先暂时不做介绍,后续有时间了我们再做介绍。

u011699626的博客 1212

mysql proxy 读写分离_关于MySQL Proxy读写分离的问题

最近做MYSQL主从复制、读写分离的事情,环境搭建完成,从MYSQL客户端测试主从复制,读写分离没有问题,但是一旦将其置入JBOSS就报下面的错误,再测试,如果直接连接数据库就没有问题,而且如果使用代理,竟然报的是org.hibernate.exception.GenericJDBCException,不知是何解,那位老兄出手相助下子.环境如下:Mysql 5.0.37 主从版本相同MysqlPr...

weixin_42364833的博客 368

S7-200SMART 中如何实现单按钮启停功能(两种方法)?

S7-200SMART 中如何实现单按钮启停功能(两种方法),Toggle库指令,状态翻转

Robot_PLC_HMI_Automation 1万+

Mysql --prepare statement

Prepared Statementsfile:///Volumes/SamSung%20SD/Material/Mysql/refman-5.6-en.html-chapter/sql-syntax.html#sql-syntax-prepared-statements MySQL 5.6 provides support for server-side prepared statements

FaN() 2798

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

MySQL的XA_prepare_event类型binlog的解析

为了支持新版的xa事务,MySQL新加了一种binlog event类型:XA_prepare 项目中使用的开源组件mysql-binlog-connector-java无法解析此种binlog event 分析源码后发现第一个问题: MySQL中一共有39种binlog event 但是mysql-binlog-connector-java组件只写了38种binlog event,少了一...

weixin_30840573的博客 309

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

MySQL的match函数在sp中使用的BUG解析

match。

GreatSQL2021的博客 504

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Mycat处理prepare binary协议的bug

今天线上使用Mycat的业务突然反馈通过golang MySQL客户端执行SQL报异常: Error 3344: StringIndexOutOfBoundsException: String index out of range: 237 复制代码查看Mycat日志也只有异常堆栈信息, 没有打出错误SQL和参数. 业务方很快定位到问题: 通过prepare binary协议执行一条INSERT语...

weixin_33862514的博客 307

XA事务与MySQL

XA事务与MySQL XA事务就是两阶段提交的一种实现方式 XA规范主要定义了事务管理器TM,和资源管理器RM之间的接口 根据2PC的规范,将一次事务分割成两个阶段 prepare阶段 TM向所有RM发送prepare指令,RM接受到指令后执行数据修改和日志记录等操作,然后返回 可以提交/不可提交 给TM (按照我的理解应该类似于MySQL在开启一个事务之后,只差最后的COMMIT或者ROLLBACK的状态) commit阶段 TM接受到所有RM的prepare结果 如果有RM返回是 不可提交 或者

日常随手记 314

c mysql prepared,c# – MySql:使用Prepared语句使用.NET / Connector可以更快地调用存储过程吗?...

我一直在阅读有关使用MySql的Prepared语句,并且.NET / Connector确实支持它们.我想知道的是,如果我使用预准备语句来调用相同的存储过程数千次,那么是否比使用预准备语句更快或更好的性能(因为存储过程应该已经编译好了)?例如:var mySqlCmd = new MySqlCommand(con, "call sp_someProcedure(@param1, @param2)...

weixin_39773215的博客 241

MySQL--Online DDL

MySQL 5.5版本DDL在MySQL 5.6.7版本前,DDL操作主要有copy和inplace两种方式,两种方式全程都需要锁表禁止写操作,允许部分时间段的读操作。copy方式: (1)新建带索引的临时表 (2)锁原表,禁止DML,允许查询 (3)将原表数据拷贝到临时表(无排序,一行一行拷贝) (4)进行rename,升级字典锁,禁止读写 (5)完成创建索引操作 ...

weixin_38168838的博客 189

mysql 定义游标里sql 实现动态条件_分布式 | DBLE 如何实现 Prepared Statement 协议

原创: 鲍凤奇 本文摘要:DBLE 是一款企业级的开源分布式中间件,江湖人送外号 “MyCat Plus”。Prepared Statement 协议是 MySQL 5.1 版本新加入的功能。MyCat 从1.6版本实现了 Prepared Statement 协议,但 MyCat 存在一些至今仍未修复的Bug。本文将从两名 DBLE 用户提交的Bug开始说起,详细解读 DBLE 是如何实现 Pr...

weixin_39614546的博客 305

MySQL DBA如何"土土"地利用源码解决没有遇到过的错误?

本篇文章记录的是遇到一个未知错误的排查过程,由于本人水平有限,如有描述不正确的欢迎指正。 问题描述 开发报错 MySQL error code 1615 (ER_NEED_REPREPARE): Prepared statement needs to be re-prepared 排查过程 乍一看,没见过这个错误啊,用大腿想了下这个应该是php程序为了防止SQL注入用的prepare执行的。赶...

Evelyn_Lv的博客 397

MySQL中char(36)被认为是GUID导致的BUG及解决方案

有时候在使用Toad或在程序中,偶尔会遇到如下的错误: System.FormatExceptionGUID 应包含带 4 个短划线的 32 位数(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)。Stack Trace: 在 System.Guid..ctor(String g) 在 MySql.Data.Types.MySqlGuid.MySql...

weixin_30745553的博客 311
上一篇: 有事务冲突时节点怎么加入MGR集群
下一篇: 使用 Vagrant 在 VirtualBox 安装 Linux 虚拟机
GreatSQL社区
博客等级 码龄5年 1210粉丝 390原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值