Agregue un nuevo sp_instr a GreatSQL sp para introducir el análisis de errores

Agregue un nuevo sp_instr a GreatSQL sp para introducir el análisis de errores

1. Descubrimiento de problemas

El sp utilizado en un desarrollo necesita agregar nuevos sp_instr para satisfacer la demanda. Sin embargo, después de agregar varios sp_instr, se descubre que el núcleo ocurrirá al ejecutar el nuevo sp.

Nota: Esta vez se utiliza GreatSQL 8.0.32-25.

1. Agregue 10 nuevos sp_instr al código init_sp_psi_keys() de sp_head.cc:

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. Agregue un nuevo código de implementación relacionado con sp_instr_stmt a sp_instr.cc, entre los cuales sql_yacc.yy y sql_lex.cc deben agregar una nueva sintaxis en consecuencia.

3. sp_rcontext.h se encuentra en la clase sp_rcontext y agrega varias variables miembro nuevas. El siguiente código es sólo un ejemplo y no tiene ningún valor práctico.

  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. Cree un nuevo sp, que contenga el contenido del nuevo sp_instr_stmt, y luego llame al sp. Resulta que la lógica del código se borra porque el valor del miembro en una lista se borra, lo que provoca un bloqueo. A continuación se muestra la pila relevante. Debido a que está involucrada la confidencialidad del código, solo se toman las pilas relevantes de la parte de código abierto.

#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. Proceso de investigación de problemas

1. Verifique cuidadosamente el código y descubra que no hay ningún problema con la lógica del código. Los valores de la lista se asignaron correctamente, pero cuando se ejecuta, se descubre que la lista se borra. Obviamente, esto es una pérdida de memoria. desbordamiento de memoria en otro lugar que hace que el espacio de elementos de la lista se ocupe o se elimine. Si el código sp se reemplaza con otra cosa, a veces fallará y otras no. El mecanismo de activación no está claro y no sé qué línea específica de código causó la pérdida de memoria.

2. Así que volví y miré el lugar donde agregué el código por primera vez. Supuse que estaba relacionado con el hecho de que agregué 10 sp_instr_stmt. Debido a que la matriz o la memoria relacionadas no se expandieron, es muy probable que esto cause. un desbordamiento de memoria.

3. Después de localizar el área sospechosa del problema, puede comenzar a investigar el código relevante. Vea el código relacionado con agregar 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. Soluciones de problemas

Después de analizar el código anterior, puede modificar el código de problema relevante realizando las siguientes modificaciones. Después de recompilar, el problema está resuelto.

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. Resumen del problema

Al agregar un nuevo sp_instr al sp de GreatSQL, debe aumentar los valores de los parámetros correspondientes en consecuencia para evitar el desbordamiento de la memoria. Si es necesario modificar otras funciones de manera similar, primero debe investigar cuidadosamente si hay configuraciones de parámetros relacionadas o definiciones de macros involucradas. de lo contrario, encontrará todo tipo de problemas inexplicables y llevará mucho tiempo investigarlos.

Los problemas descubiertos esta vez son errores introducidos por funciones recién agregadas. También debemos prestar atención a problemas similares en el desarrollo y la aplicación reales. Si no tenemos cuidado, caeremos en trampas.

Los problemas anteriores también existen en MySQL/Percona.


Disfruta de GreatSQL :)

Acerca de GreatSQL

GreatSQL es una base de datos nacional independiente de código abierto adecuada para aplicaciones de nivel financiero. Tiene muchas características principales, como alto rendimiento, alta confiabilidad, alta facilidad de uso y alta seguridad. Puede usarse como un reemplazo opcional de MySQL o Percona Server. y se utiliza en entornos de producción online, completamente gratuito y compatible con MySQL o Percona Server.

Enlaces relacionados: Comunidad GreatSQL Gitee GitHub Bilibili

Gran comunidad SQL:

imagen

Sugerencias y comentarios sobre recompensas de la comunidad: https://greatsql.cn/thread-54-1-1.html

Detalles de la presentación del premio del blog comunitario: https://greatsql.cn/thread-100-1-1.html

(Si tiene alguna pregunta sobre el artículo o tiene ideas únicas, puede ir al sitio web oficial de la comunidad para preguntarlas o compartirlas ~)

Grupo de intercambio técnico:

Grupo WeChat y QQ:

Grupo QQ: 533341697

Grupo WeChat: agregue GreatSQL Community Assistant (ID de WeChat:) wanlidbccomo amigo y espere a que el asistente de la comunidad lo agregue al grupo.

Un programador nacido en los años 90 desarrolló un software de portabilidad de vídeo y ganó más de 7 millones en menos de un año. ¡El final fue muy duro! Los estudiantes de secundaria crean su propio lenguaje de programación de código abierto como una ceremonia de mayoría de edad: comentarios agudos de los internautas: debido al fraude desenfrenado, confiando en RustDesk, el servicio doméstico Taobao (taobao.com) suspendió los servicios domésticos y reinició el trabajo de optimización de la versión web Java 17 es la versión Java LTS más utilizada. Cuota de mercado de Windows 10. Alcanzando el 70%, Windows 11 continúa disminuyendo. Open Source Daily | Google apoya a Hongmeng para hacerse cargo de los teléfonos Android de código abierto respaldados por Docker; Electric cierra la plataforma abierta Apple lanza el chip M4 Google elimina el kernel universal de Android (ACK) Soporte para la arquitectura RISC-V Yunfeng renunció a Alibaba y planea producir juegos independientes en la plataforma Windows en el futuro
{{o.nombre}}
{{m.nombre}}

Supongo que te gusta

Origin my.oschina.net/GreatSQL/blog/11102185
Recomendado
Clasificación