Adicione novo sp_instr ao GreatSQL sp para introduzir análise de bugs

Adicione novo sp_instr ao GreatSQL sp para introduzir análise de bugs

1. Descoberta de problemas

O sp usado em um desenvolvimento precisa adicionar novo sp_instr para atender a demanda. Porém, após adicionar vários sp_instr, verifica-se que o núcleo ocorrerá ao executar o novo sp.

Nota: GreatSQL 8.0.32-25 é usado desta vez.

1. Adicione 10 novos sp_instr ao 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. Adicione novo código de implementação relacionado a sp_instr_stmt em sp_instr.cc, entre os quais sql_yacc.yy e sql_lex.cc precisam adicionar uma nova sintaxe de acordo.

3. sp_rcontext.h está localizado na classe sp_rcontext e adiciona diversas novas variáveis ​​de membro. O código a seguir é apenas um exemplo e não tem valor prático.

  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. Crie um novo sp, que contém o conteúdo do novo sp_instr_stmt, e então chame o sp. Acontece que a lógica do código foi limpa porque o valor do membro em uma lista foi limpo, o que leva a uma falha. Abaixo está a pilha relevante. Como a confidencialidade do código está envolvida, apenas as pilhas relevantes da parte de código aberto são utilizadas.

#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. Processo de investigação de problemas

1. Verifique cuidadosamente o código e descubra que não há nenhum problema com a lógica do código. Os valores da lista foram realmente atribuídos com sucesso, mas durante a execução, a lista foi limpa. Obviamente, isso é um vazamento de memória ou. estouro de memória em outro lugar que faz com que o espaço do elemento da lista seja ocupado ou excluído vazio. Se o código sp for substituído por outra coisa, às vezes ele falhará e às vezes não. O mecanismo de disparo não está claro e não sei qual linha específica de código causou o vazamento de memória.

2. Então voltei e olhei para o local onde adicionei o código pela primeira vez, imaginei que estava relacionado ao fato de ter adicionado 10 sp_instr_stmt. Como a matriz ou memória relacionada não foi expandida, era muito provável que isso causasse. um estouro de memória.

3. Depois de localizar a área suspeita de problema, você pode começar a investigar o código relevante. Veja o código relacionado à adição de 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. Soluções de problemas

Depois de analisar o código acima, você pode modificar o código do problema relevante fazendo as seguintes modificações. Após a recompilação, o problema está resolvido.

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. Resumo do problema

Ao adicionar um novo sp_instr ao sp do GreatSQL, você precisa aumentar os valores dos parâmetros correspondentes de acordo para evitar estouro de memória. Se outras funções precisarem ser modificadas de forma semelhante, você deve primeiro investigar cuidadosamente se há configurações de parâmetros relacionadas ou definições de macro envolvidas. caso contrário, você encontrará todos os tipos de problemas inexplicáveis ​​e levará muito tempo para investigá-los.

Os problemas descobertos desta vez são bugs introduzidos por funções recém-adicionadas. Também devemos prestar atenção a problemas semelhantes no desenvolvimento e na aplicação reais.

Os problemas acima também existem no MySQL/Percona.


Aproveite o GreatSQL :)

Sobre GreatSQL

GreatSQL é um banco de dados doméstico independente de código aberto adequado para aplicativos de nível financeiro. Possui muitos recursos básicos, como alto desempenho, alta confiabilidade, alta facilidade de uso e alta segurança. e é utilizado em ambientes de produção online, totalmente gratuito e compatível com MySQL ou Percona Server.

Links relacionados: Guia da comunidade GreatSQL GitHub Bilibili

Comunidade GreatSQL:

imagem

Sugestões e feedback de recompensas da comunidade: https://greatsql.cn/thread-54-1-1.html

Detalhes do envio do prêmio do blog da comunidade: https://greatsql.cn/thread-100-1-1.html

(Se você tiver alguma dúvida sobre o artigo ou tiver ideias exclusivas, você pode acessar o site oficial da comunidade para perguntar ou compartilhá-las ~)

Grupo de intercâmbio técnico:

Grupo WeChat e QQ:

Grupo QQ: 533341697

Grupo WeChat: Adicione o GreatSQL Community Assistant (WeChat ID:) wanlidbccomo amigo e espere que o assistente da comunidade adicione você ao grupo.

Um programador nascido na década de 1990 desenvolveu um software de portabilidade de vídeo e faturou mais de 7 milhões em menos de um ano. O final foi muito punitivo! Alunos do ensino médio criam sua própria linguagem de programação de código aberto como uma cerimônia de maioridade - comentários contundentes de internautas: Contando com RustDesk devido a fraude desenfreada, serviço doméstico Taobao (taobao.com) suspendeu serviços domésticos e reiniciou o trabalho de otimização de versão web Java 17 é a versão Java LTS mais comumente usada no mercado do Windows 10 Atingindo 70%, o Windows 11 continua a diminuir Open Source Daily | Google apoia Hongmeng para assumir o controle de telefones Android de código aberto apoiados pela ansiedade e ambição da Microsoft; Electric desliga a plataforma aberta Apple lança chip M4 Google exclui kernel universal do Android (ACK) Suporte para arquitetura RISC-V Yunfeng renunciou ao Alibaba e planeja produzir jogos independentes na plataforma Windows no futuro
{{o.nome}}
{{m.nome}}

Acho que você gosta

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