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
malformed
erros - 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 há 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 repita
order 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 DataTime
os resultados elegíveis são classificados e a varredura completa da tabela é realmente executada e o problema se repete
- Quando há 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 repita
-
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 total950131(rowno:950130)
de registros e, em seguida,SQLITE_DONE
termina - Quando
sql = malformed
,950300
relatar 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!
- Quando a consulta é normal, apenas os
- Quando
-
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
- O registro de data e hora final:
- Possível razão 1: o banco de dados foi restaurado automaticamente
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