sqlite本身的事务并不支持嵌套,而savepoint方法虽然支持嵌套,但是,使用起来比较复杂。下面,提供一种针对线程数据库连接的事务嵌套模式,如果是在单线程中操作数据库,则可以进一步简化实现 (采用静态变量保存事务计数即可)。
在代码中,使用了windows下的线程槽的概念,其是针对每个线程保留单独的一份数据
#include "sqlite3.h" /** * @class LockHelp * @brief a lock class */ class CLockHelp { public: CLockHelp() { ::InitializeCriticalSection(&m_CriticalSection); } ~CLockHelp() { ::DeleteCriticalSection(&m_CriticalSection); }
/// lock void lock() { ::EnterCriticalSection(&m_CriticalSection); }
/// unlock void unlock() { ::LeaveCriticalSection(&m_CriticalSection); } private: CLockHelp(const NLock&); CLockHelp& operator=(const NLock&);
private: CRITICAL_SECTION m_CriticalSection; };
/** * @class CTransaction * @brief 启动、回滚、提交事务操作 */ class CTransaction { public: CTransaction(sqlite *pConnection); ~CTransaction(void);
public: /** * @brief 获取m_dwTLSRollbackTrans,表明数据库操作出错 * @retval TLS中的值 */ void SetRollbackCounter();
private: /** * @brief 获取TLS中的值 * @param dwIdx: TLS索引 * @retval TLS中的值 */ INT64 GetCounter(DWORD dwIdx);
/** * @brief 设置TLS中的值 * @param dwIdx: TLS索引 * @param nCount: 待设定的值 */ void SetCounter(DWORD dwIdx,INT64 nCount);
private: /// 线程局部存储变量 /// 是否调用BeginTransaction() static DWORD m_dwTLSBeginTransIdx;
/// 是否调用RollbackTransaction() static DWORD m_dwTLSRollbackTransIdx; /// 线程锁 static CLockHelp m_CriticalLock;
/// CTableHandler对象 sqlite3 *m_pConnection; };
#include "Transaction.h"
DWORD CTransaction::m_dwTLSBeginTransIdx = ::TlsAlloc(); DWORD CTransaction::m_dwTLSRollbackTransIdx = ::TlsAlloc(); CLockHelp CTransaction::m_CriticalLock;
CTransaction::CTransaction(CTableHandler *pTableHandler) : m_pTableHandler(pTableHandler) { // 加锁 m_CriticalLock.lock();
INT64 nBeginTrans(GetCounter(m_dwTLSBeginTransIdx)); if (nBeginTrans == 0) { if (!m_pTableHandler->BeginTransaction()) { // 设置为0 SetCounter(m_dwTLSBeginTransIdx,nBeginTrans); return; } }
SetCounter(m_dwTLSBeginTransIdx,nBeginTrans + 1); }
CTransaction::~CTransaction(void) { INT64 nEndTrans(GetCounter(m_dwTLSBeginTransIdx)); if (nEndTrans == 0) { // 启动事务失败 INT64 nRollbackTrans(GetCounter(m_dwTLSRollbackTransIdx)); if (nRollbackTrans == 1) { SetCounter(m_dwTLSRollbackTransIdx,0); }
// 解锁 m_CriticalLock.unlock(); return; } if (nEndTrans == 1) { INT64 nRollbackTrans(GetCounter(m_dwTLSRollbackTransIdx)); if (nRollbackTrans == 1) { m_pTableHandler->RollbackTransaction(); SetCounter(m_dwTLSRollbackTransIdx,0); } else { m_pTableHandler->CommitTransaction(); } }
SetCounter(m_dwTLSBeginTransIdx,nEndTrans - 1);
// 解锁 m_CriticalLock.unlock(); }
void CTransaction::SetRollbackCounter() { SetCounter(m_dwTLSRollbackTransIdx,1); }
INT64 CTransaction::GetCounter(DWORD dwIdx) { return reinterpret_cast<INT64>(::TlsGetValue(dwIdx)); }
void CTransaction::SetCounter(DWORD dwIdx,INT64 nCount) { ::TlsSetValue(dwIdx,reinterpret_cast<void *>(nCount)); } (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|