SQLite事务并发访问问题?

 

//描述:执行命令	
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<sizeof(szBlob); i++)
					TRACE("%02x ", szBlob[i]);
				TRACE("\n");
			}
			
			sqlite3_finalize(stmt);
			CommitTransaction(db, pszThreadName);
            Sleep(10);
		}
	}
	else if (iThrd==3 || iThrd==4) //读数据
	{
		while (1)
		{
			char *queryFieldx20000200SameDate1 = "SELECT StartTime FROM TbReal WHERE MtrAddr==\"000337448041 \"";
			if (sqlite3_prepare(db, queryFieldx20000200SameDate1, -1, &stmt, 0) == SQLITE_OK)
			{
				BYTE bRdBuf[128]={0};
				if ((iRet=sqlite3_step(stmt)) == SQLITE_ROW)
				{
					if ((iLen=sqlite3_column_bytes(stmt, 0)) > 0)
						memcpy(bRdBuf, sqlite3_column_blob(stmt, 0), iLen);
				}
				TRACE("%s: ", pszThreadName);
				for (int i=0; i<iLen; i++)
					TRACE("%02x ", bRdBuf[i]);
				TRACE("\n");
			}
			sqlite3_finalize(stmt);
            Sleep(10);
		}
	}
}	
	
	
	
TThreadRet TrancsationThread(void* pvArg)
{
	TThrdPara *pTrdPara = (TThrdPara*)pvArg;

	TRACE("TrancsationThread: idx=%d, TrdName=%s\n", pTrdPara->idx, 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;
			}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值