バグ分析を導入するために新しい sp_instr を GreatSQL sp に追加します

バグ分析を導入するために新しい sp_instr を GreatSQL sp に追加します

1. 問題の発見

開発で使用するspは、需要に応じて新しいsp_instrを追加する必要がありますが、いくつかのsp_instrを追加した後、新しいspを実行するとコアが発生することがわかります。

注: 今回は GreatSQL 8.0.32-25 を使用します。

1. sp_head.cc の init_sp_psi_keys() コードに 10 個の新しい sp_instr を追加します。

void init_sp_psi_keys() {
  mysql_statement_register(category, &sp_instr_stmt1::psi_info, 1);
  mysql_statement_register(category, &sp_instr_stmt2::psi_info, 1);
  mysql_statement_register(category, &sp_instr_stmt3::psi_info, 1);
  ......
  mysql_statement_register(category, &sp_instr_stmt10::psi_info, 1);
}

2. 新しい sp_instr_stmt 関連の実装コードを sp_instr.cc に追加します。そのうち sql_yacc.yy と sql_lex.cc には、それに応じて新しい構文を追加する必要があります。

3. sp_rcontext.h はクラス sp_rcontext にあり、いくつかの新しいメンバー変数を追加します。次のコードは単なる例であり、実用的な価値はありません。

  Field *m_return_value_fld_tmp{m_return_value_fld};
  Field *m_return_value_fld_tmp1{m_return_value_fld};
  Field *m_return_value_fld_tmp2{m_return_value_fld};

4. 新しい sp_instr_stmt の内容を含む新しい sp を作成し、その sp を呼び出します。リスト内のメンバーの値がクリアされるため、コード ロジックがクリアされ、クラッシュが発生することがわかります。以下は関連するスタックです。コードの機密性が関係するため、オープン ソース部分の関連するスタックのみが取得されます。

#0  0x0000555558f3f3d9 in base_list_iterator::next_fast (this=0x7fffe01e9de0)
    at /sql/sql_list.h:371
#1  0x0000555558fc59b7 in List_iterator_fast<Create_field>::operator++ (this=0x7fffe01e9de0)
    at /sql/sql_list.h:605
#2  0x0000555559753ea2 in create_tmp_table_from_fields (thd=0x7fff20001050, field_list=..., 
    is_virtual=false, select_options=0, alias=0x0)
    at /sql/sql_tmp_table.cc:2131
#3  0x0000555559084a09 in Item_xx::val_str (this=0x7fff20b673c8)
    at /sql/item_func.cc:10796
#4  0x0000555558fa408b in Item::save_in_field_inner (this=0x7fff20b673c8, field=0x7fff20b9b1a8, 
    no_conversions=false) at /sql/item.cc:8202
#5  0x0000555558fa3c43 in Item::save_in_field (this=0x7fff20b673c8, field=0x7fff20b9b1a8, 
    no_conversions=false) at /sql/item.cc:8144
#6  0x0000555559400322 in sp_eval_expr (thd=0x7fff20001050, result_field=0x7fff20b9b1a8, 
    expr_item_ptr=0x7fff20b67620) at /sql/sp.cc:3613
#7  0x000055555943b1d1 in sp_rcontext::set_variable (this=0x7fff20b85d80, thd=0x7fff20001050, 
    field=0x7fff20b9b1a8, value=0x7fff20b67620)
    at /sql/sp_rcontext.cc:1023
#8  0x0000555558fc3a8e in sp_rcontext::set_variable (this=0x7fff20b85d80, thd=0x7fff20001050, 
    var_idx=1, value=0x7fff20b67620)
    at /sql/sp_rcontext.h:176
打印crash处的信息,发现list里面的值被清空了。
(gdb) p tmp
$1 = (list_node *) 0x0

2. 問題調査プロセス

1. コードを注意深くチェックし、コード ロジックに問題がないことを確認します。リストの値は実際に正常に割り当てられていますが、実行すると、明らかにメモリ リークまたはリストがクリアされていることがわかります。他の場所でメモリ オーバーフローが発生し、リストの要素スペースが占有されるか削除されます。 sp コードが他のものに置き換えられると、クラッシュする場合もあれば、クラッシュしない場合もあります。トリガーのメカニズムは明確ではなく、コードのどの行がメモリ リークを引き起こしたのかわかりません。

2. それで、最初にコードを追加した場所に戻って調べました。これは、10 sp_instr_stmt を追加したことに関連していると推測しました。これは、関連する配列またはメモリが拡張されていないためです。メモリオーバーフロー。

3. 問題が疑われる領域を特定したら、関連するコードの調査を開始できます。 sp_instr の追加に関連するコードを表示します。

添加sp_instr实现代码如下:
mysql_statement_register(category, &sp_instr_stmt1::psi_info, 1);

于是继续往下面调查mysql_statement_register实现的代码,看到这里果然用到了statement_class_max:
PFS_statement_key register_statement_class(const char *name, uint name_length,
                                           PSI_statement_info *info) {
  /* See comments in register_mutex_class */
  uint32 index;
  PFS_statement_class *entry;

  REGISTER_CLASS_BODY_PART(index, statement_class_array, statement_class_max,
                           name, name_length)

接着查看statement_class_max的赋值的地方:
int init_statement_class(uint statement_class_sizing) {
  int result = 0;
  statement_class_dirty_count = statement_class_allocated_count = 0;
  statement_class_max = statement_class_sizing;

通过搜索代码查到statement_class_sizing相关的参数配置的地方,看到这里有一个SP_PSI_STATEMENT_INFO_COUNT宏定义,这个值跟sp_instr的数量有关。
static Sys_var_ulong Sys_pfs_max_statement_classes(
    "performance_schema_max_statement_classes",
    "Maximum number of statement instruments.",
    READ_ONLY GLOBAL_VAR(pfs_param.m_statement_class_sizing),
    CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 256),
    DEFAULT((ulong)SQLCOM_END + (ulong)COM_END + 5 +
            SP_PSI_STATEMENT_INFO_COUNT + CLONE_PSI_STATEMENT_COUNT),
    BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);

继续全文搜索,发现在sp_head.h定义了,这里的值为16,数了一下现存的sp_instr个数刚好为16个,至此问题原因发现,因为我加了10个sp_instr,而这个宏定义的值没有跟着增加,导致内存溢出。
#define SP_PSI_STATEMENT_INFO_COUNT 16

3. 問題の解決策

上記のコードを解析した後、次の変更を加えて、関連する問題のコードを変更できます。再コンパイル後、問題は解決します。

sp_head.h修改SP_PSI_STATEMENT_INFO_COUNT宏定义:
#define SP_PSI_STATEMENT_INFO_COUNT 26

因为增加了Sys_pfs_max_statement_classes的default值,因为相关配置范围也要跟着增加,因此把range相应加大。
static Sys_var_ulong Sys_pfs_max_statement_classes(
    "performance_schema_max_statement_classes",
    "Maximum number of statement instruments.",
    READ_ONLY GLOBAL_VAR(pfs_param.m_statement_class_sizing),
    CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 256 * 2),
    DEFAULT((ulong)SQLCOM_END + (ulong)COM_END + 5 +
            SP_PSI_STATEMENT_INFO_COUNT + CLONE_PSI_STATEMENT_COUNT),
    BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);

4. 問題の概要

GreatSQL の sp に新しい sp_instr を追加する場合、メモリ オーバーフローを防ぐために、それに応じて対応するパラメータ値を増やす必要があります。他の関数も同様に変更する必要がある場合は、関連するパラメータ設定やマクロ定義が存在するかどうかを最初に注意深く調査する必要があります。そうしないと、あらゆる種類の不可解な問題が発生し、調査に多くの時間がかかります。

今回発見された問題は、新たに追加された機能によってもたらされたバグであり、実際の開発やアプリケーションにおいても同様の問題に注意を払う必要があります。

上記の問題は MySQL/Percona にも存在します。


GreatSQL をお楽しみください :)

GreatSQL について

GreatSQL は、金融レベルのアプリケーションに適した国産の独立したオープンソース データベースであり、高パフォーマンス、高信頼性、高使いやすさ、高セキュリティなどの多くのコア機能を備えており、MySQL または Percona Server のオプションの代替として使用できます。オンラインの実稼働環境で使用され、完全に無料で、MySQL または Percona Server と互換性があります。

関連リンク: GreatSQL コミュニティ Gitee GitHub Bilibili

GreatSQL コミュニティ:

画像

コミュニティの報酬に関する提案とフィードバック: https://greatsql.cn/thread-54-1-1.html

コミュニティ ブログ賞を受賞した投稿の詳細: https://greatsql.cn/thread-100-1-1.html

(記事について質問がある場合、または独自の洞察がある場合は、公式コミュニティ Web サイトにアクセスして質問したり共有したりできます~)

技術交流グループ:

WeChat & QQ グループ:

QQグループ: 533341697

WeChat グループ: GreatSQL コミュニティ アシスタント (WeChat ID: wanlidbc) を友達として追加し、コミュニティ アシスタントがあなたをグループに追加するまで待ちます。

1990 年代生まれのプログラマーがビデオ移植ソフトウェアを開発し、1 年足らずで 700 万以上の利益を上げました。結末は非常に罰的でした。 高校生が成人式にオープンソースプログラミング言語を自作―ネチズンの鋭いコメント: 詐欺横行でRustDesk依存、国内サービスの タオバオ(taobao.com)は国内サービスを一時停止、ウェブ版の最適化作業を再開 Java最も一般的に使用されている Java LTS バージョンは 17 、Windows 11 は減少し続ける Open Source Daily | Google がオープンソースの Rabbit R1 を支持、Microsoft の不安と野心; Electricがオープンプラットフォームを閉鎖 AppleがM4チップをリリース GoogleがAndroidユニバーサルカーネル(ACK)を削除 RISC-Vアーキテクチャのサポート Yunfengがアリババを辞任し、将来的にはWindowsプラットフォームで独立したゲームを制作する予定
{{名前}}
{{名前}}

おすすめ

転載: my.oschina.net/GreatSQL/blog/11102185