Fügen Sie GreatSQL SP ein neues sp_instr hinzu, um eine Fehleranalyse einzuführen

Fügen Sie GreatSQL SP ein neues sp_instr hinzu, um eine Fehleranalyse einzuführen

1. Problemerkennung

Der in einer Entwicklung verwendete SP muss neue sp_instr hinzufügen, um den Bedarf zu decken. Nach dem Hinzufügen mehrerer sp_instr wird jedoch festgestellt, dass beim Ausführen des neuen SP ein Kern auftritt.

Hinweis: Dieses Mal wird GreatSQL 8.0.32-25 verwendet.

1. Fügen Sie 10 neue sp_instr zum init_sp_psi_keys()-Code von sp_head.cc hinzu:

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. Fügen Sie sp_instr.cc neuen sp_instr_stmt-bezogenen Implementierungscode hinzu, wobei sql_yacc.yy und sql_lex.cc entsprechend neue Syntax hinzufügen müssen.

3. sp_rcontext.h befindet sich in der Klasse sp_rcontext und fügt mehrere neue Mitgliedsvariablen hinzu. Der folgende Code ist nur ein Beispiel und hat keinen praktischen Wert.

  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. Erstellen Sie einen neuen SP, der den Inhalt des neuen sp_instr_stmt enthält, und rufen Sie dann den SP auf. Es stellt sich heraus, dass die Codelogik gelöscht wird, da der Wert eines Mitglieds in einer Liste gelöscht wird, was zu einem Absturz führt. Unten ist der entsprechende Stapel. Da es um die Vertraulichkeit des Codes geht, werden nur die relevanten Stacks des Open-Source-Teils verwendet.

#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. Problemuntersuchungsprozess

1. Überprüfen Sie den Code sorgfältig und stellen Sie fest, dass die Werte der Liste tatsächlich erfolgreich zugewiesen wurden. Beim Ausführen wird jedoch festgestellt, dass dies ein Speicherverlust ist Speicherüberlauf an anderer Stelle, der dazu führt, dass der Elementbereich der Liste belegt oder gelöscht wird. Wenn der SP-Code durch etwas anderes ersetzt wird, stürzt er manchmal ab und manchmal nicht. Der Auslösemechanismus ist nicht klar und ich weiß nicht, welche bestimmte Codezeile den Speicherverlust verursacht hat.

2. Also ging ich zurück und schaute mir die Stelle an, an der ich den Code zum ersten Mal hinzugefügt hatte. Ich vermutete, dass dies mit der Tatsache zusammenhing, dass ich 10 sp_instr_stmt hinzugefügt hatte. Da das zugehörige Array oder der Speicher nicht erweitert wurde, war es sehr wahrscheinlich, dass dies dazu führen würde ein Speicherüberlauf.

3. Nachdem Sie den vermuteten Problembereich gefunden haben, können Sie mit der Untersuchung des relevanten Codes beginnen. Sehen Sie sich den Code zum Hinzufügen von sp_instr an.

添加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. Problemlösungen

Nachdem Sie den obigen Code analysiert haben, können Sie den relevanten Problemcode ändern, indem Sie die folgenden Änderungen vornehmen. Nach dem Neukompilieren ist das Problem behoben.

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. Problemübersicht

Wenn Sie ein neues sp_instr zu GreatSQLs sp hinzufügen, müssen Sie die entsprechenden Parameterwerte entsprechend erhöhen, um einen Speicherüberlauf zu verhindern. Wenn andere Funktionen auf ähnliche Weise geändert werden müssen, müssen Sie zunächst sorgfältig prüfen, ob verwandte Parameterkonfigurationen oder Makrodefinitionen beteiligt sind. Andernfalls werden Sie auf alle möglichen unerklärlichen Probleme stoßen und die Untersuchung nimmt viel Zeit in Anspruch.

Die dieses Mal entdeckten Probleme sind Fehler, die durch neu hinzugefügte Funktionen verursacht werden. Wir sollten auch auf ähnliche Probleme in der tatsächlichen Entwicklung und Anwendung achten. Wenn wir nicht aufpassen, werden wir in Fallstricke geraten.

Die oben genannten Probleme bestehen auch in MySQL/Percona.


Viel Spaß mit GreatSQL :)

Über GreatSQL

GreatSQL ist eine inländische unabhängige Open-Source-Datenbank, die für Anwendungen auf Finanzebene geeignet ist. Sie verfügt über viele Kernfunktionen wie hohe Leistung, hohe Zuverlässigkeit, hohe Benutzerfreundlichkeit und hohe Sicherheit. Sie kann als optionaler Ersatz für MySQL oder Percona Server verwendet werden und wird in Online-Produktionsumgebungen verwendet, völlig kostenlos und kompatibel mit MySQL oder Percona Server.

Verwandte Links: GreatSQL Community Gitee GitHub Bilibili

GreatSQL-Community:

Bild

Vorschläge und Feedback zu Community-Belohnungen: https://greatsql.cn/thread-54-1-1.html

Details zur preisgekrönten Einreichung des Community-Blogs: https://greatsql.cn/thread-100-1-1.html

(Wenn Sie Fragen zu dem Artikel haben oder einzigartige Erkenntnisse gewinnen möchten, können Sie diese auf der offiziellen Community-Website stellen oder teilen~)

Technische Austauschgruppe:

WeChat- und QQ-Gruppe:

QQ-Gruppe: 533341697

WeChat-Gruppe: Fügen Sie GreatSQL Community Assistant (WeChat-ID:) wanlidbcals Freund hinzu und warten Sie, bis der Community-Assistent Sie der Gruppe hinzufügt.

Ein in den 1990er Jahren geborener Programmierer hat eine Videoportierungssoftware entwickelt und in weniger als einem Jahr über 7 Millionen verdient. Das Ende war sehr bestrafend! High-School-Schüler erstellen im Rahmen einer Coming-of-Age-Zeremonie ihre eigene Open-Source-Programmiersprache – scharfe Kommentare von Internetnutzern: Der inländische Dienst Taobao (taobao.com) verließ sich aufgrund des grassierenden Betrugs auf RustDesk und stellte die inländischen Dienste ein und startete die Arbeit zur Optimierung der Webversion von Java neu 17 ist die am häufigsten verwendete Java LTS-Version. Windows 11 erreicht weiterhin einen Rückgang. Open Source Daily unterstützt die Übernahme von Open Source Rabbit R1; Electric schließt die offene Plattform Apple veröffentlicht M4-Chip Google löscht Android Universal Kernel (ACK) Unterstützung für RISC-V-Architektur Yunfeng ist von Alibaba zurückgetreten und plant, in Zukunft unabhängige Spiele auf der Windows-Plattform zu produzieren
{{o.name}}
{{m.name}}

Ich denke du magst

Origin my.oschina.net/GreatSQL/blog/11102185
Empfohlen
Rangfolge