欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MySQL的prepare使用及遇到bug解析過(guò)程

 更新時(shí)間:2022年05月07日 15:36:29   作者:GreatSQL  
在一次開(kāi)發(fā)中使用 MySQL PREPARE 以后,從 prepare 直接取 name 賦值給 lex->prepared_stmt_name 然后給 EXECUTE 用,發(fā)現(xiàn)有一定概率找不到 prepare stmt 的 name,于是開(kāi)始動(dòng)手調(diào)查問(wèn)題發(fā)生的原因,本文給大家分享mysql prepare使用及問(wèn)題解決,感興趣的朋友一起看看吧

一、問(wèn)題發(fā)現(xiàn)

在一次開(kāi)發(fā)中使用 MySQL PREPARE 以后,從 prepare 直接取 name 賦值給 lex->prepared_stmt_name 然后給 EXECUTE 用,發(fā)現(xiàn)有一定概率找不到 prepare stmt 的 name,于是開(kāi)始動(dòng)手調(diào)查問(wèn)題發(fā)生的原因。

SQL語(yǔ)句示例:

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

報(bào)錯(cuò):
SQL Error [1243] [HY000]: Unknown prepared statement handler (dbms_sql_stmt4??p??]UU) given to EXECUTE

二、問(wèn)題調(diào)查過(guò)程

1、根據(jù)報(bào)錯(cuò)信息找到對(duì)應(yīng)源碼,發(fā)現(xiàn)在MySQL_sql_stmt_execute里面有判斷當(dāng)找不到 stmt name 時(shí)候報(bào)錯(cuò)信息。

這里的 name 此時(shí)已經(jīng)是亂碼了。

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、這個(gè) lex->prepared_stmt_name 是從 prepare name 中賦值的,于是調(diào)查 prepare 這個(gè) name 設(shè)置的函數(shù)。

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 后面出現(xiàn)了亂碼,說(shuō)明 m_nam e最后不是 \0 結(jié)束,而是別的字符。

3、接著到 execute 的函數(shù)看一下這個(gè) name 值,發(fā)現(xiàn)確實(shí)后面跟的不是 \0 結(jié)束符,而是變?yōu)閬y碼。于是這里當(dāng)然會(huì)報(bào)錯(cuò)找不到該 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;
# 結(jié)果報(bào)錯(cuò)了。

三、問(wèn)題解決方案

通過(guò)以上 gdb 跟蹤過(guò)程我們可以發(fā)現(xiàn) prepare 存 name 的時(shí)候存放方式有問(wèn)題導(dǎo)致 name 最后沒(méi)有結(jié)束符,于是回頭看一下set_name 的代碼,于是發(fā)現(xiàn)以下代碼問(wèn)題:

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));←這里問(wèn)題
  return m_name.str == nullptr;
}
# 箭頭處發(fā)現(xiàn)存 name 時(shí)候申請(qǐng)的內(nèi)存長(zhǎng)度為 name_arg.length,沒(méi)有把最后的 \0 一起存放進(jìn)去,導(dǎo)致最后少了結(jié)束符,這就有概率導(dǎo)致查找 name 出錯(cuò)。

于是把 name_arg.length 改為 name_arg.length+1,重新編譯代碼問(wèn)題解決。

四、問(wèn)題總結(jié)

c++ 中字符串的使用一定要注意最后的結(jié)束符\0,如果因?yàn)樯俜峙淞艘粋€(gè)長(zhǎng)度導(dǎo)致結(jié)束符沒(méi)有存進(jìn)去,最后存放的字符串就會(huì)產(chǎn)生問(wèn)題。

到此這篇關(guān)于MySQL的prepare使用及遇到bug解析過(guò)程的文章就介紹到這了,更多相關(guān)mysql prepare使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 深入解析MySQL的窗口函數(shù)

    深入解析MySQL的窗口函數(shù)

    這篇文章主要介紹了深入解析MySQL的窗口函數(shù),窗口可以理解為記錄集合,窗口函數(shù)就是在滿足某種條件的記錄集合上執(zhí)行的特殊函數(shù),即:應(yīng)用在窗口內(nèi)的函數(shù),需要的朋友可以參考下
    2023-07-07
  • CentOS 安裝redis和MySQL

    CentOS 安裝redis和MySQL

    這篇文章主要介紹了CentOS 安裝redis和MySQL的相關(guān)資料,需要的朋友可以參考下
    2019-08-08
  • MySQL數(shù)據(jù)庫(kù)開(kāi)啟、關(guān)閉、查看函數(shù)功能的方法

    MySQL數(shù)據(jù)庫(kù)開(kāi)啟、關(guān)閉、查看函數(shù)功能的方法

    這篇文章主要介紹了MySQL數(shù)據(jù)庫(kù)開(kāi)啟、關(guān)閉、查看函數(shù)功能的方法,本文為解決一個(gè)錯(cuò)誤總結(jié)而來(lái),錯(cuò)誤信息本文一同給出,需要的朋友可以參考下
    2014-10-10
  • MySQL結(jié)合使用數(shù)據(jù)庫(kù)分析工具SchemaSpy的方法

    MySQL結(jié)合使用數(shù)據(jù)庫(kù)分析工具SchemaSpy的方法

    這篇文章主要介紹了MySQL結(jié)合使用數(shù)據(jù)庫(kù)分析工具SchemaSpy的方法,需要的朋友可以參考下
    2015-06-06
  • MYSQL存儲(chǔ)過(guò)程 注釋詳解

    MYSQL存儲(chǔ)過(guò)程 注釋詳解

    這篇文章主要介紹MYSQL存儲(chǔ)的過(guò)程,本文圍繞MYSQL存儲(chǔ)詳細(xì)展開(kāi)文章內(nèi)容,并附上詳細(xì)代碼解析,需要的下伙伴可以參考一下,希望對(duì)你有所幫助
    2021-10-10
  • SQL中distinct 和 row_number() over() 的區(qū)別及用法

    SQL中distinct 和 row_number() over() 的區(qū)別及用法

    這篇文章主要介紹了SQL中distinct 和 row_number() over() 的區(qū)別及用法的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • 實(shí)例驗(yàn)證MySQL|update字段為相同的值是否會(huì)記錄binlog

    實(shí)例驗(yàn)證MySQL|update字段為相同的值是否會(huì)記錄binlog

    這篇文章主要介紹了實(shí)例驗(yàn)證MySQL|update字段為相同的值是否會(huì)記錄binlog,幫助大家更好的理解和學(xué)習(xí)MySQL數(shù)據(jù)庫(kù),感興趣的朋友可以了解下
    2020-10-10
  • MySql安裝及登錄詳解

    MySql安裝及登錄詳解

    這篇文章主要介紹了MySql安裝及登錄詳解,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2017-03-03
  • MySQL同步數(shù)據(jù)Replication的實(shí)現(xiàn)步驟

    MySQL同步數(shù)據(jù)Replication的實(shí)現(xiàn)步驟

    本文主要介紹了MySQL同步數(shù)據(jù)Replication的實(shí)現(xiàn)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • MySQL InnoDB 事務(wù)鎖源碼分析

    MySQL InnoDB 事務(wù)鎖源碼分析

    InnoDB 事務(wù)鎖,事務(wù)鎖實(shí)現(xiàn)起來(lái)的代碼卻是又臭又硬的好大一坨,各種細(xì)節(jié),今天小編在這里整理一個(gè)源碼閱讀筆記,把那一坨加鎖相關(guān)的代碼提煉出來(lái),感興趣的小伙伴別忘記收藏奧
    2021-09-09

最新評(píng)論