El extraño error mal formado de sqlite3 (1)
fenómeno
- El equipo de campo genera e inserta datos a gran escala y, cuando las anomalías del equipo extraen la base de datos para su inspección, notifican los
malformed
errores. - sqlite3 versión 3.8.6
- Tamaño del archivo de base de datos 210 MB
Problema de posicionamiento
-
Tamaño de datos
select count(*) from DataSheet; /*结果*/ 950131
-
Clave primaria
primary key(ctype,id,DataTime)
-
Recurrencia ( experto en SQLite )
select * from DataSheet where id='000537719140' order by DataTime; /*malformed*/ select * from DataSheet where ctype=5002 and id='000537719140' order by DataTime; /*OK*/
Como se mencionó anteriormente, la única diferencia entre las dos sentencias SQL es si la condición oad está incluida en la cláusula where. ¿Por qué es así? Primero realice la siguiente comparación SQL:
select * from DataSheet where id='000537719140'; /*OK*/ select * from DataSheet order by DataTime; /*malformed, 全表扫描*/
- Cuando hay ctype, identificación, y DataTime en el donde cláusula, el índice (clave principal) es exitosa. En este momento, los índices elegibles se clasifican, por lo que el problema no se repite
order by DataTime
- Cuando la cláusula where no coincide exactamente con ctype, id y DataTime , se pierde el índice (clave principal),
order by DataTime
se ordenan los resultados que cumplen las condiciones y se realiza el escaneo completo de la tabla y el problema se repite
- Cuando hay ctype, identificación, y DataTime en el donde cláusula, el índice (clave principal) es exitosa. En este momento, los índices elegibles se clasifican, por lo que el problema no se repite
-
Código de prueba: línea de posicionamiento
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);
- Cuándo
sql = okayQuery
, consultar un total950131(rowno:950130)
de registros y luegoSQLITE_DONE
finalizar - Cuándo
sql = malformed
,950300
informar de un error al obtener el primer registro11 (SQLITE_CORRUPT)
- Cuando la consulta es normal, solo se pueden recorrer los
950131(rowno:950130)
registros - Cuando la consulta es anormal, se produjo un error al pasar a
950300(rowno:950301)
un registro.
- Cuando la consulta es normal, solo se pueden recorrer los
- Cuándo
-
Código de prueba: tiempo de posicionamiento
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);
Salida:
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
Iniciar sesión
- 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 la base de datos para el día siguiente
- 2019/12/21 base de datos
- Tamaño del archivo de la base de datos: 210 MB
- Mismo tamaño de base de datos
- Ver menú
- Okay
análisis
- La base de datos 2019/12/20 tiene un problema de formato incorrecto, pero la base de datos 2019/12/21 no tiene este problema. Puede ser:
- Posible motivo 1: la base de datos se ha restaurado automáticamente
- El ciclo de datos no ha llegado: recuperación automática sin limpieza
- Sin función de reparación en el dispositivo
- Posible causa dos: problema de copia de la base de datos
- La marca de tiempo del registro final:
12-20 11:24:21.057# ...
- Si primero extrae la base de datos con ftp y luego guarda el registro de shell, cuando extrae la base de datos, es posible que la base de datos esté ejecutando una transacción, lo que causa el problema
- La marca de tiempo del registro final:
- Posible motivo 1: la base de datos se ha restaurado automáticamente
En conclusión
- Cuando ftp extrae la base de datos, la base de datos está ejecutando una transacción de escritura de datos, lo que provoca el problema de formato incorrecto.