//描述:执行命令
void ExecSqlCmd(sqlite3 *db, const char *sql, const char *pszThrdName)
{
int iRet;
char *err_msg = 0;
char buf[1024];
if ((iRet = sqlite3_exec(db, sql, NULL, 0, &err_msg)) != SQLITE_OK)
{
sqlite3_free(err_msg);
TRACE("%s error, sql=%s\n", pszThrdName, sql);
}
}
//描述:开始事务处理
int BeginTransaction(sqlite3 *db, const char *pszThrdName)
{
//return ExecSqlCmd(db, "BEGIN", pszThrdName);
return ExecSqlCmd(db, "BEGIN IMMEDIATE TRANSACTION", pszThrdName);
//ExecSqlCmd(db, "BEGIN EXCLUSIVE TRANSACTION", pszThrdName);
//ExecSqlCmd(db, "BEGIN TRANSACTION", pszThrdName);
}
//描述:结束事务处理
void CommitTransaction(sqlite3 *db, const char *pszThrdName)
{
ExecSqlCmd(db, "COMMIT", pszThrdName);
}
//描述:回滚事务处理
void RollBackTransaction(sqlite3 *db, const char *pszThrdName)
{
ExecSqlCmd(db, "ROLLBACK", pszThrdName);
}
typedef struct TThrdPara{
int idx;
const char *pszThrName;
};
sqlite3 *db = NULL;
void TestTransactionLock(int iThrd, const char *pszThreadName)
{
sqlite3_stmt *stmt;
int iRet, iLen;
char *pszSqliteName = USER_DATA_SQLITE3_PATH"gwooDb";
char *errmsg = NULL;
char **results;
static bool fInit = false;
if (!fInit)
{
fInit = true;
if ((iRet=sqlite3_open(pszSqliteName, &db)) > 0)
{
TRACE("can't open db!\n", sqlite3_errmsg(db));
sqlite3_close(db);
return;
}
char *sqlCreateTable = "CREATE TABLE TbReal (StartTime DATETIME,SuccTime DATETIME,SaveTime DATETIME,MtrAddr BLOB, x20000200 BLOB, x20010200 BLOB)";
iRet = sqlite3_exec(db, sqlCreateTable, 0, 0, &errmsg);
}
if (iThrd==1 || iThrd==2) //写数据
{
while (1)
{
BeginTransaction(db, pszThreadName);
char *insertSql = "INSERT INTO TbReal (StartTime, SuccTime, SaveTime, MtrAddr, x20000200) \
VALUES(DATETIME(1551262800, 'unixepoch'), DATETIME(1551263014, 'unixepoch'), DATETIME(1551262800, 'unixepoch'), \"000337448041\",?)";
if ((iRet=sqlite3_prepare(db, insertSql, -1, &stmt, NULL)) == SQLITE_OK)
{
char szBlob[] = {0x01, 0x03, 0x12, 0x01, 0x0a, 0x12, 0x00, 0x14, 0x12, 0x00, 0x1e };
sqlite3_bind_blob(stmt, 1, szBlob, sizeof(szBlob), SQLITE_TRANSIENT);
if ((iRet=sqlite3_step(stmt)) != SQLITE_DONE)
{
sqlite3_finalize(stmt);
CommitTransaction(db, pszThreadName);
TRACE("ThreadName: %s sqlite3_step error!\n", pszThreadName);
return;
}
TRACE("%s: ", pszThreadName);
for (int i=0; i 0)
memcpy(bRdBuf, sqlite3_column_blob(stmt, 0), iLen);
}
TRACE("%s: ", pszThreadName);
for (int i=0; iidx, pTrdPara->pszThrName);
TestTransactionLock(pTrdPara->idx, pTrdPara->pszThrName);
return 1;
}
void MakeThreadTest()
{
TThrdPara tTrdPara1, tTrdPara2;
tTrdPara1.idx = 1;
tTrdPara1.pszThrName = "线程1";
NewThread(TrancsationThread, &tTrdPara1, 8192, THREAD_PRIORITY_NORMAL);
tTrdPara2.idx = 2;
tTrdPara2.pszThrName = "线程2";
NewThread(TrancsationThread, &tTrdPara2, 8192, THREAD_PRIORITY_NORMAL);
//NewThread(CheckNetThread, NULL, 8192, THREAD_PRIORITY_NORMAL);
tTrdPara2.idx = 3;
tTrdPara2.pszThrName = "线程3";
NewThread(TrancsationThread, &tTrdPara2, 8192, THREAD_PRIORITY_NORMAL);
//NewThread(CheckNetThread, NULL, 8192, THREAD_PRIORITY_NORMAL);
tTrdPara2.idx = 4;
tTrdPara2.pszThrName = "线程4";
NewThread(TrancsationThread, &tTrdPara2, 8192, THREAD_PRIORITY_NORMAL);
//NewThread(CheckNetThread, NULL, 8192, THREAD_PRIORITY_NORMAL);
while(1)
{
Sleep(1000);
}
}
int main()
{
MakeThreadTest();
}
未加锁时事务开始、提交出现报错,日志如下
TrancsationThread: idx=1, TrdName=线程1
TrancsationThread: idx=2, TrdName=线程2
线程2 error, iRet=21, sql=BEGIN IMMEDIATE TRANSACTION, err_msg=(null)
TrancsationThread: idx=3, TrdName=线程3
TrancsationThread: idx=4, TrdName=线程4
线程1: ok
线程4: ok
线程3: ok
线程2: ok
线程4: ok
线程1: ok
线程3: ok
线程3: ok
线程2: ok
线程4: ok
线程1: ok
线程4: ok
线程3: ok
线程4: ok
线程2: ok
线程1: ok
线程3: ok
线程4: ok
线程2: ok
线程3: ok
线程1: ok
线程4: ok
线程2: ok
线程3: ok
线程4: ok
线程3: ok
线程1: ok
线程2: ok
线程4: ok
线程3: ok
线程1: ok
线程4: ok
线程3: ok
线程4: ok
线程2: ok
线程1: ok
线程3: ok
线程4: ok
线程2: ok
线程4: ok
线程1: ok
线程3: ok
线程4: ok
线程3: ok
线程2: ok
线程4: ok
线程3: ok
线程1: ok
线程2: ok
线程4: ok
线程3: ok
线程3: ok
线程4: ok
线程1: ok
线程3: ok
线程2: ok
线程4: ok
线程3: ok
线程1: ok
线程4: ok
线程2: ok
线程3: ok
线程1: ok
线程4: ok
线程3: ok
线程2: ok
线程4: ok
线程3: ok
线程1: ok
线程4: ok
线程3: ok
线程2: ok
线程3: ok
线程4: ok
线程1: ok
线程4: ok
线程3: ok
线程2: ok
线程1: ok
线程4: ok
线程3: ok
线程2: ok
线程4: ok
线程3: ok
线程1: ok
线程2: ok
线程4: ok
线程3: ok
线程3: ok
线程1: ok
线程4: ok
线程3: ok
线程2: ok
线程1: ok
线程4: ok
线程3: ok
线程2: ok
线程3: ok
线程4: ok
线程1: ok
线程2: ok
线程4: ok
线程3: ok
线程3: ok
线程4: ok
线程1: ok
线程3: ok
线程4: ok
线程2: ok
线程1: ok
线程4: ok
线程3: ok
线程3: ok
线程4: ok
线程2: ok
线程3: ok
线程4: ok
线程1: ok
线程2: ok
线程3: ok
线程4: ok
线程1: ok
线程3: ok
线程4: ok
线程3: ok
线程2: ok
线程1: ok
线程4: ok
线程3: ok
线程2: ok
线程4: ok
线程1: ok
线程3: ok
线程4: ok
线程3: ok
线程4: ok
线程2: ok
线程4: ok
线程3: ok
线程1: ok
线程2: ok
线程4: ok
线程3: ok
线程1: ok
线程3: ok
线程2: ok
线程4: ok
线程1: ok
线程3: ok
线程2: ok
线程4: ok
线程3: ok
线程1: ok
线程4: ok
线程3: ok
线程2: ok
线程4: ok
线程1: ok
线程3: ok
线程3: ok
线程4: ok
线程2: ok
线程1: ok
线程3: ok
线程4: ok
线程3: ok
线程2: ok
线程1: ok
线程4: ok
线程3: ok
线程4: ok
线程2: ok
线程3: ok
线程4: ok
线程1: ok
线程2: ok
线程4: ok
线程3: ok
线程1: ok
线程4: ok
线程3: ok
线程4: ok
线程2: ok
线程1: ok
线程3: ok
线程4: ok
线程2: ok
线程1: ok
线程4: ok
线程2: ok
线程3: ok
线程1: ok
线程3: ok
线程4: ok
上面代码需增加实物开启的防错机制检测
if (BeginTransaction(db, pszThreadName) != SQLITE_OK)
{
Sleep(10);
continue;
}