加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

SQLITE事务

发布时间:2020-12-13 00:12:01 所属栏目:百科 来源:网络整理
导读:sqlite本身的事务并不支持嵌套,而savepoint方法虽然支持嵌套,但是,使用起来比较复杂。下面,提供一种针对线程数据库连接的事务嵌套模式,如果是在单线程中操作数据库,则可以进一步简化实现 (采用静态变量保存事务计数即可)。 在代码中,使用了windows

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)); }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读