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

数据库2025-11-03 23:56:0179682

   

 一、的的问题发现 二、用中问题调查过程

 三、解析问题解决方案

 四、过程问题总结

一、的的问题发现

在一次开发中使用 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 EXECUTE1.2.3.4.5.

二、问题调查过程

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; }1.2.3.4.5.6.7.8.9.10.11.

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;}1.2.3.4.5.6.

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:24472447 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 结束,而是别的字符。1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.

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:19441944 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;# 结果报错了。企商汇1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.

三、问题解决方案

通过以上 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 出错。1.2.3.4.5.6.7.

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

四、问题总结

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

本文地址:http://www.bzve.cn/html/453c1599531.html
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

热门文章

全站热门

搭建个人服务器的费用标准(详细解析自己搭建服务器所需的费用和预算)

台式电脑扩展显示教程(一步步教你如何扩展台式电脑的显示屏,让工作效率翻倍)

华硕F81se系列电脑的用户在安装Ubuntu12.04系统是出现了错误,导致Ubuntu12.04安装失败,那么是什么原因导致系统安装失败呢?想要在华硕F81se上使用Ubuntu12.04系统怎么办?下面小编就给大家介绍下解决方法。问题:从ubuntu官网上下载了12.04的安装包,下了个usb installer,把系统烧到u盘以后,在u盘里run了下,总是出现下面的错误:Cannot allocate resource for EISA slot 1Cannot allocate resource for EISA slot 2Cannot allocate resource for EISA slot 3Cannot allocate resource for EISA slot 4Cannot allocate resource for EISA slot 5Cannot allocate resource for EISA slot 6Cannot allocate resource for EISA slot 7Cannot allocate resource for EISA slot 8解决方法:华硕电脑开机的时候,按F2进入bios设置,选择security选项,会看到如下图所示:按键盘上的上下键,把光标移动到I/O Interface Security 选项,敲回车,进入下图:默认情况下,这里面的所有的选项都是UNLOCKED 将最后一个选项New Card Interface 设置为LOCKED 这样就可以进入系统了,有人提到要将Wireless NetWork Interface 也设置为LOCED 这样有利于安装,要注意:ODD Interface 和USB Interface 千万不要设置为LOCKED 这样就关闭了USB 和光驱的功能。装完系统以后要把New Card Interface 设置为LOCKED,否则ubuntu 12.04将启动不了,其他的都要设置为UBLOCKED,到这里,基本上系统装的就没问题了。上面就是Ubuntu 12.04在华硕F81se电脑上安装失败的解决方法介绍了,只要你安装本文的步骤实施,你就能轻松使用上Ubuntu 12.04系统了。

Ubuntu 14.04继续在Dash搜索中加入了在线搜索结果,其中主要是来自Amazon的内容,其展示结果如下图所示,假如不希望显示在线搜索结果,你可以通过下面的方法实现。打开终端(Ctrl+Alt+T)输入下面的命令,gsettings set com.canonical.Unity.Lenses remote-content-search ‘none’完成后关闭窗口并注销当前用户,再次使用Dash进行搜索时将不会出现在线结果,假如你想继续使用在线搜索结果,可通过在终端中输入下面的命令恢复。复制代码代码如下:gsettings set com.canonical.Unity.Lenses remote-content-search ‘all’

联想电脑账户密码错误的原因及解决方法(探索联想电脑账户密码错误的背后问题,教你轻松解决困扰)

ubuntu怎么开启root帐号?ubuntu 的root账户具有最高的系统权限,它类似于windows系统中的管理员账号,但是比windows系统中管理员账号的权限更高,一般都情况下不要使用root账户,但是有的时候还是要使用root账户,下面就为大家介绍ubuntu 开启root帐号方法!说明:小编的这个建议只适合于10.10之前版本的ubuntu系统,后面的11.04,11.10。。。14.04系统因为采用的默认桌面不同,所以本经验不适用,若要使用,那么请安装GNOME桌面ubuntu 开启root帐号方法:1、点击系统菜单栏中的“应用程序”,然后点击附件,之后在打开的附件子菜单中选择“终端”2、点击终端后就打开如下图所示的终端工具,大家要做的所有操作都在这个窗口中进行3、其实root账户是存在的,只是需要我们给它设置一个密码,然后使用的时候用root用户名登陆,然后输入对应的密码就就以root用户登录了,所以开启root账户,实际上就是给root用户设置一个密码的过程,下面我们就来给root设置密码,另外还需要注意的是,只能使安全ubuntu系统的时候创建的用户账号才能启用root账号,使用下面的命令来给root账号设置密码:sudo passwd root执行上面的命令后,就会提示要求输入当前用户的密码4、确认我们的密码正确后,就会提示“Enter new UNIX password”,这个就是设置密码的提示,输入大家要设置的密码,注意在设置密码的时候是看不到任何字符的,只有我们自己注意了5、输入密码后敲回车键,之后会提示我们再次确认密码,输入确认密码,然后按Enter回车键6、密码设置成功,这样root用户也就开启了,以后大家要使用root账号的时候只要使用相关切换命令就可以了,具体怎么切换到root账号的命令请看小编另外一个经验的分享END以上就是ubuntu怎么开启root帐号的方法,希望对大家有所帮助!

华硕F81se系列电脑的用户在安装Ubuntu12.04系统是出现了错误,导致Ubuntu12.04安装失败,那么是什么原因导致系统安装失败呢?想要在华硕F81se上使用Ubuntu12.04系统怎么办?下面小编就给大家介绍下解决方法。问题:从ubuntu官网上下载了12.04的安装包,下了个usb installer,把系统烧到u盘以后,在u盘里run了下,总是出现下面的错误:Cannot allocate resource for EISA slot 1Cannot allocate resource for EISA slot 2Cannot allocate resource for EISA slot 3Cannot allocate resource for EISA slot 4Cannot allocate resource for EISA slot 5Cannot allocate resource for EISA slot 6Cannot allocate resource for EISA slot 7Cannot allocate resource for EISA slot 8解决方法:华硕电脑开机的时候,按F2进入bios设置,选择security选项,会看到如下图所示:按键盘上的上下键,把光标移动到I/O Interface Security 选项,敲回车,进入下图:默认情况下,这里面的所有的选项都是UNLOCKED 将最后一个选项New Card Interface 设置为LOCKED 这样就可以进入系统了,有人提到要将Wireless NetWork Interface 也设置为LOCED 这样有利于安装,要注意:ODD Interface 和USB Interface 千万不要设置为LOCKED 这样就关闭了USB 和光驱的功能。装完系统以后要把New Card Interface 设置为LOCKED,否则ubuntu 12.04将启动不了,其他的都要设置为UBLOCKED,到这里,基本上系统装的就没问题了。上面就是Ubuntu 12.04在华硕F81se电脑上安装失败的解决方法介绍了,只要你安装本文的步骤实施,你就能轻松使用上Ubuntu 12.04系统了。

AWStats是在Sourceforge上发展很快的一个基于Perl的WEB日志分析工具。相对于另外一个非常优秀的开放源代码的日志分析工具Webalizer,AWStats的优势在于:复制代码代码如下:接下来,你需要启用 Apache 的 CGI 模块。运行以下命令来启动 CGI:复制代码代码如下:现在,重新启动 Apache 以使改变生效。复制代码代码如下:复制代码代码如下:现在,你需要在配置文件中做一些修改:复制代码代码如下:像下面这样修改一下:复制代码代码如下:保存并关闭文件。修改配置文件后,你需要用服务器的当前日志建立初步统计。你可以这样做:复制代码代码如下:复制代码代码如下:添加下面那一行来让 AWStats 每十分钟更新一次。复制代码代码如下:保存并关闭文件。结论AWStats 是一个非常有用的工具,可以让你对网站的状况了如指掌,并能协助你分析网站。它非常容易安装和配置。假如你有任何疑问,请在下面发表评论。

热门文章

友情链接

滇ICP备2023006006号-39