c++ - sqlite3 会产生非确定性错误吗?
问题描述
在 Sqlite3 数据库(VS 2015 Express 测试)中保存和读取数据时出现随机错误。
做了简单的跟踪,有时可以看到更新后 select 读取的内容有所修改,但不确定它来自哪里或是什么原因。有时它们很频繁,但现在它们非常罕见 - 例如,在短时间内同一测试用例的几次手动运行期间,上次 2 倍不同的 uint8_t 值......
我如何检查是什么导致了这个-DB/FS/sqlite3.c 问题或其他问题?
我正在测试仅具有单个 SSD 驱动器的 3 个月大的 NTB。
我的跟踪代码:
sqlite3_trace_v2(数据库,SQLITE_TRACE_STMT | SQLITE_TRACE_ROW,DBtrace::Trace,0);
class DBtrace {
public:
static bool logNow;
static std::string log;
DBtrace(bool enable = false) { logNow = enable; }
DBtrace & DBtrace::Instance()
{
static DBtrace instance;
return instance;
}
static int Trace(unsigned int d, void *m, void *p, void *x);
};
#include "sqlite3.h"
#include "db_trace.hpp"
#include <stdio.h>
#include <algorithm>
using namespace std;
namespace databaseNS
{
bool DBtrace::logNow;
std::string DBtrace::log;
static int isUseless(int c) { return c < 32; }
bool BothAreSpaces(char lhs, char rhs) { return (lhs == rhs) && (lhs < 32); }
int DBtrace::Trace(unsigned int d, void *m, void *p, void *x) {
if (!logNow) return 0;
string sql;
std::string::iterator new_end;
sqlite3_value *v;
sqlite3_stmt *pStmt = reinterpret_cast<sqlite3_stmt *>(p);
int cc = sqlite3_column_count(pStmt);
switch (d)
{
case SQLITE_TRACE_STMT:
sql = sqlite3_expanded_sql(pStmt);
new_end = std::unique(sql.begin(), sql.end(), BothAreSpaces);
sql.erase(new_end, sql.end());
sql += "\r\n";
log += sql;
break;
case SQLITE_TRACE_ROW:
int n = sqlite3_bind_parameter_count(pStmt);
for (int i = 0; i < cc; i++)
{
sql = sqlite3_column_name(pStmt, i);
v = sqlite3_column_value(pStmt, i);
if (v->flags & MEM_Int) {
sql += ":" + std::to_string(v->u.i) + ", ";
log += sql;
}
if (v->flags & MEM_Str) {
sql += ":";
sql += v->z;
sql += ", ";
log += sql;
};
}
log += "\r\n";
break;
}
return 0;
}
}
并且在 sqlite3.c ( db_trace.hpp )中找到了许多必需的声明
#include <string>
/**
* @brief Routine for preparation sql queries needed for data handling
*
* @return true if success, false otherwise
*
*/
/*
** Integers of known sizes. These typedefs might change for architectures
** where the sizes very. Preprocessor macros are available so that the
** types can be conveniently redefined at compile-type. Like this:
**
** cc '-DUINTPTR_TYPE=long long int' ...
*/
#ifndef UINT32_TYPE
# ifdef HAVE_UINT32_T
# define UINT32_TYPE uint32_t
# else
# define UINT32_TYPE unsigned int
# endif
#endif
#ifndef UINT16_TYPE
# ifdef HAVE_UINT16_T
# define UINT16_TYPE uint16_t
# else
# define UINT16_TYPE unsigned short int
# endif
#endif
#ifndef INT16_TYPE
# ifdef HAVE_INT16_T
# define INT16_TYPE int16_t
# else
# define INT16_TYPE short int
# endif
#endif
#ifndef UINT8_TYPE
# ifdef HAVE_UINT8_T
# define UINT8_TYPE uint8_t
# else
# define UINT8_TYPE unsigned char
# endif
#endif
#ifndef INT8_TYPE
# ifdef HAVE_INT8_T
# define INT8_TYPE int8_t
# else
# define INT8_TYPE signed char
# endif
#endif
#ifndef LONGDOUBLE_TYPE
# define LONGDOUBLE_TYPE long double
#endif
typedef sqlite_int64 i64; /* 8-byte signed integer */
typedef sqlite_uint64 u64; /* 8-byte unsigned integer */
typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
typedef UINT16_TYPE u16; /* 2-byte unsigned integer */
typedef INT16_TYPE i16; /* 2-byte signed integer */
typedef UINT8_TYPE u8; /* 1-byte unsigned integer */
typedef INT8_TYPE i8; /* 1-byte signed integer */
typedef struct FuncDef FuncDef;
struct sqlite3_value {
union MemValue {
double r; /* Real value used when MEM_Real is set in flags */
i64 i; /* Integer value used when MEM_Int is set in flags */
int nZero; /* Extra zero bytes when MEM_Zero and MEM_Blob set */
const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */
FuncDef *pDef; /* Used only when flags==MEM_Agg */
} u;
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
u8 eSubtype; /* Subtype for this value */
int n; /* Number of characters in string value, excluding '\0' */
char *z; /* String or BLOB value */
/* ShallowCopy only needs to copy the information above */
char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */
int szMalloc; /* Size of the zMalloc allocation */
u32 uTemp; /* Transient storage for serial_type in OP_MakeRecord */
sqlite3 *db; /* The associated database connection */
void(*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */
#ifdef SQLITE_DEBUG
Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
u16 mScopyFlags; /* flags value immediately after the shallow copy */
#endif
};
/* One or more of the following flags are set to indicate the validOK
** representations of the value stored in the Mem struct.
**
** If the MEM_Null flag is set, then the value is an SQL NULL value.
** For a pointer type created using sqlite3_bind_pointer() or
** sqlite3_result_pointer() the MEM_Term and MEM_Subtype flags are also set.
**
** If the MEM_Str flag is set then Mem.z points at a string representation.
** Usually this is encoded in the same unicode encoding as the main
** database (see below for exceptions). If the MEM_Term flag is also
** set, then the string is nul terminated. The MEM_Int and MEM_Real
** flags may coexist with the MEM_Str flag.
*/
#define MEM_Null 0x0001 /* Value is NULL (or a pointer) */
#define MEM_Str 0x0002 /* Value is a string */
#define MEM_Int 0x0004 /* Value is an integer */
#define MEM_Real 0x0008 /* Value is a real number */
#define MEM_Blob 0x0010 /* Value is a BLOB */
#define MEM_AffMask 0x001f /* Mask of affinity bits */
/* Available 0x0020 */
/* Available 0x0040 */
#define MEM_Undefined 0x0080 /* Value is undefined */
#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
#define MEM_TypeMask 0xc1ff /* Mask of type bits */
解决方案
推荐阅读
- javascript - 如何在applab中创建上传图片的功能?
- javascript - 如何让javascript执行一个php文件
- google-cloud-firestore - firebase-functions 上的 firebase-admin 无法正确初始化 App
- swift - SwiftUI:在我看来,文本被“...”截断
- python - 如何在python中使用硒单击与另一个元素相同的元素?
- python - 在 os.system 使用 subprocess.call 中的文件输入时不起作用
- java - 从 Firebase 存储下载 url 是“com.google.android.gms.tasks.zzu@441922b”,不显示
- linux - 用于使用 xargs 对另一个命令生成的搜索文本的一个命令的输出进行 grep 的一个衬垫
- javascript - 未在移动浏览器上检索会话存储
- android - 共享内存方法是否通过活页夹进行进程间通信?