O estranho erro malformado de sqlite3 (1)

O estranho erro malformado de sqlite3 (1)

fenômeno

  • O equipamento de campo gera e insere dados em grande escala, e quando as anormalidades do equipamento puxam o banco de dados para inspeção, relata os malformederros
  • sqlite3 versão 3.8.6
  • Tamanho do arquivo de banco de dados de 210 MB

Problema de posicionamento

  • Tamanho dos dados

    select count(*) from DataSheet;
    /*结果*/
    950131
    
  • Chave primária

    primary key(ctype,id,DataTime)
    
  • Recorrência ( SQLite Expert )

    select * from DataSheet where id='000537719140' order by DataTime;  /*malformed*/
    select * from DataSheet where ctype=5002 and id='000537719140' order by DataTime; /*OK*/
    

    Conforme mencionado acima, a única diferença entre as duas instruções SQL é se a condição oad está incluída na cláusula where. Por que isso acontece? Primeiro, execute a seguinte comparação SQL:

    select * from DataSheet where id='000537719140';  /*OK*/
    select * from DataSheet order by DataTime;     /*malformed, 全表扫描*/
    
    • Quando ctype, id e DataTime na cláusula where , o índice (chave primária) é atingido. Nesse momento, os índices elegíveis são classificados, de modo que o problema não se repitaorder by DataTime
    • Quando a cláusula where não corresponde exatamente a ctype, id e DataTime , o índice (chave primária) é perdido e order by DataTimeos resultados elegíveis são classificados e a varredura completa da tabela é realmente executada e o problema se repete
  • Código de teste: linha de posicionamento

    char * malformed = "select rowid, ctype, id, StartTime, DataTime from DataSheet;"; /*malformed*/
    char * okayQuery = "select rowid, ctype, id, DataTime from DataSheet;"; /*OK*/
    char * sql = okayQuery;
    sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, NULL);
    ncols = sqlite3_column_count(stmt);
    int rowno = 0;
    do {
          
          
        rc = sqlite3_step(stmt);
        switch (rc) {
          
          
        case SQLITE_ROW:	break;
        case SQLITE_DONE:	rowno = -100;	break;
        default:			fprintf(stderr, "rowno = %d, sqlite3 error %d\n", rowno, rc);  break;
        }
        if (rowno >= 0) {
          
           rowno++; }
    }
    while (rowno >= 0);
    sqlite3_finalize(stmt);
    
    • Quando sql = okayQuery, consulta um total 950131(rowno:950130)de registros e, em seguida, SQLITE_DONEtermina
    • Quando sql = malformed, 950300relatar um erro ao buscar o primeiro registro11 (SQLITE_CORRUPT)
      • Quando a consulta é normal, apenas os 950131(rowno:950130)registros podem ser percorridos
      • Quando a consulta é anormal, ocorre um erro ao passar para 950300(rowno:950301)um registro!
  • Código de teste: tempo de posicionamento

    char * malformed = "select rowid, ctype, id, DataTime, StartTime from DataSheet;";
    char * okayQuery = "select rowid, ctype, id, DataTime from DataSheet;";
    char * sql = malformed;
    sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, NULL);
    ncols = sqlite3_column_count(stmt);
    int rowno = 0;
    do {
          
          
      rc = sqlite3_step(stmt);
      switch (rc) {
          
          
      case SQLITE_ROW:
        if (rowno >= 950129 && rowno <= 950301/* 950300 */) {
          
          
          rowid	 = sqlite3_column_int(stmt, 0);
          ctype  = (char*)sqlite3_column_text(stmt, 1);
          id = (char*)sqlite3_column_text(stmt, 2);
          colltime = (char *)sqlite3_column_text(stmt, 3);
          fprintf(stderr, "rowno: %d, rowid: %i, ctype: %s, id:%s, time:%s\n", rowno, rowid, (ctype?ctype:snull),(id?id:snull), (colltime?colltime:snull));
        }
        break;
      case SQLITE_DONE:	rowno = -100;	break;
      default:			fprintf(stderr, "rowno = %d, sqlite3 error %d\n", rowno, rc);	break;
      }
      if (rowno >= 0) {
          
           rowno++; }
    }
    while (rowno >= 0);
    sqlite3_finalize(stmt);
    

    Resultado:

    rowno: 950129, rowid: 4478623, ctype: 5002, id:001548532328, time:20191220105300
    rowno: 950130, rowid: 4478624, ctype: 5002, id:001548532328, time:20191220105400
    ...
    rowno: 950297, rowid: 4478791, ctype: 5002, id:001548532342, time:20191220105800
    rowno: 950298, rowid: 4478792, ctype: 5002, id:001548532342, time:20191220105900
    rowno: 950299, rowid: 4478793, ctype: 5002, id:001548532342, time:20191220110100
    rowno = 950300, sqlite3 error 11
    rowno: 950301, rowid: 3526517, ctype: 5002, id:005410401490, time:20191214202200
    

Registro

  • 20191220.log
    #12-20 11:21:30.098: 写入[38] 20191220-111700  ...
    #12-20 11:21:30.433: 写入[39] 20191220-111800  ...
    #12-20 11:21:30.434: 写入[40] 20191220-111900  ...
    

Verifique o banco de dados para o dia seguinte

  • Banco de dados de 21/12/2019
  • Tamanho do arquivo de banco de dados: 210 MB
    • Mesmo tamanho de banco de dados
  • Verifique o menu
    • Está bem

análise

  • O banco de dados 20/12/2019 tem um problema malformado, mas o banco de dados 21/12/2019 não tem esse problema. Pode ser:
    • Possível razão 1: o banco de dados foi restaurado automaticamente
      • O ciclo de dados ainda não chegou: recuperação automática sem limpeza
      • Sem função de reparo no dispositivo
    • Possível causa dois: problema de cópia do banco de dados
      • O registro de data e hora final: 12-20 11:24:21.057# ...
      • Se você puxar o banco de dados por ftp primeiro e, em seguida, salvar o log do shell, quando você puxar o banco de dados, é possível que o banco de dados esteja executando uma transação, o que causa o problema

Em conclusão

  • Quando ftp puxa o banco de dados, o banco de dados está executando uma transação de gravação de dados, o que causa o problema malformado

Acho que você gosta

Origin blog.csdn.net/hylaking/article/details/104394677
Recomendado
Clasificación