内存数据库实现中涉及数据的同步一致性问题,可以实现高效的记录锁来尽量减少同步的开销。
下图是一个内存数据库数记录锁的实现分析:
一个MDB服务端中会包含多个Table,每个Table会包含一个或多个Index键值,操作某张表中数据记录时需要对该表中某个键值加锁,就会锁定该条记录不再被其他线程同时操作。每个MDB服务库中会包含一个内存命名锁管理器(CNamedLockMemMgr),该MDB服务初始化时针对每个Table中的索引键值都创建一个内存命名锁(CNamedLockMem)并返回锁的在命名锁管理器中索引,后续锁操作时指定该索引即可。
命名锁管理器提供的锁操作接口为:
void lock(CLockInfo* pLockInfo, int64 llID, CLockSession& cLockSession )
void lock(CLockInfo* pLockInfo, CFSet<int64>& lstID, CLockSession& cLockSession )
int32 is_lock(CLockInfo* pLockInfo, int64 llID, CLockSession& cLockSession)
void unlock(CLockInfo* pLockInfo, CLockSession& cLockSession )
对某个表的键值key加锁过程如下:
1、通过初始化时得到的该表的Index列键值锁信息CLockInfo来找到其位于命名锁管理器中创建的内存命名锁(CNamedLockMem)对象;
2、将键值Key插入找到的CNamedLockMem对象的已锁定键值Set中,调用内部的CNamedLock对象对键值Key加锁;
3、CNamedLock根据建锁信息中指定的m_nLockModule数,创建了相应的多记录锁(CMultiLock)对象,对某个键值Key根据m_nLockModule取模,即可以得到要操作的多记录锁对象。
4、得到多记录锁对象(CMultiLock)进行lock操作,CMultiLock对象内部维护了通过该锁Lock的所有记录的信息,包含锁定的键值、键值当前锁定的状态、当前锁定该键值的线程和事务号、等待该锁的线程数、该锁的加锁时间。
void lock(const T& data, CLockSession& cLockSession )
{
pthread_mutex_lock( &m_lock); //操作内部锁定记录信息时需互斥加锁
int nPos = add_data( data); //如果不存键值Key信息,需要扩展增加锁记录数组
if(m_pLockSession[nPos].m_llThreadID == cLockSession.m_llThreadID &&
m_pLockSession[nPos].m_llSessionID == cLockSession.m_llSessionID &&
m_pLockStatus[nPos]
)
{//同一个线程和事务已经锁定该记录的处理
pthread_mutex_unlock( &m_lock);
if(CMultiLockAttr::get_recurLockFlag())
{
return;
}
else
{
THROW_MFEXCEPTION(MF_ERROR_LOCK_FAILED, "recursive lock failed ");
}
}
m_pWanted[nPos]++; //等待该锁的数量+1
timespec ts;
int iTime = 0;
while( m_pLockStatus[nPos])
{//该记录已被其他线程或事务锁定
if(CMultiLockAttr::get_timedLockFlag())
{//超时锁
if(iTime ==0 )
{//设定锁超时时间
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += CMultiLockAttr::get_lockTime();
iTime ++;
}
if(ETIMEDOUT == pthread_cond_timedwait( &m_cond, &m_lock, &ts))
{
m_pWanted[nPos]--;
pthread_mutex_unlock( &m_lock);
THROW_MFEXCEPTION(MF_ERROR_LOCK_TIMEOUT, "timed lock timedout");
}
}
else
{//交出执行权等待解锁事件
pthread_cond_wait( &m_cond, &m_lock);
}
}
//获取到锁
m_pLockStatus[nPos] = 1;
m_pLockSession[nPos].m_llThreadID = cLockSession.m_llThreadID;
m_pLockSession[nPos].m_llSessionID = cLockSession.m_llSessionID;
m_pWanted[nPos]--;
pthread_mutex_unlock( &m_lock);
}
void unlock(const T& data, CLockSession& cLockSession )
{
pthread_mutex_lock( &m_lock);
int nPos = find_data( data);
if( nPos != -1 &&
( m_pLockSession[nPos].m_llThreadID == cLockSession.m_llThreadID || cLockSession.m_llThreadID == 0 ) &&
( m_pLockSession[nPos].m_llSessionID == cLockSession.m_llSessionID || cLockSession.m_llSessionID == 0 ) )
{
m_pLockStatus[nPos] = 0;
m_pLockSession[nPos].m_llThreadID = 0;
m_pLockSession[nPos].m_llSessionID = 0;
if( m_pWanted[nPos])
{//有其他人在等待,广播解锁事件
pthread_cond_broadcast( &m_cond);
}
}
pthread_mutex_unlock( &m_lock);
}
相关推荐
mdb库结构记录保存.rar
资源介绍:。易语言mdb数据库结构记录保存源码。资源作者:。资源界面:。资源下载:。
MDB 协议MDB 协议MDB 协议
MDB 为一个主从结构的串行总线接口标准, 采用 9600bps 的波 特率通信。 主从操作模式,MDB 规定总线有唯一 1 个主机和最多 32 个外设。 每个外设有唯一的地址和命令。 所有通信的外设都是主机完 成初始化的。 1.2 ...
mdb修改,mdb查看
MDB协议接口售货机非现金支付测试工具,用于连接RS232-MDB适配器到自动售货机MDB接口,实现自助设备的移动支付。
易语言源码易语言mdb库结构记录保存源码.rar
# -*- coding:utf-8 -*- __author__ = 'mayi' ...#增加记录 def mdb_add(conn, cur, sql): """ 功能:向数据库插入数据 :param conn: 数据库连接 :param cur: 游标 :param sql: sql语句 :ret
java操作Access.mdb数据库的实现.pdf
MDB还原MDB还原MDB还原MDB还原MDB还原MDB还原MDB还原MDB还原MDB还原MDB还原MDB还原MDB还原MDB还原MDB还原MDB还原
MDB-RS232专业版测试工具,可以通过威佛MDB-RS232适配器对MDB纸币器(08H),硬币器(30H),非现金支付1(10H),非现金支付2(60H),USB设备(40H),年龄验证设备(68H)进行综合测试。当然下载测试工具之前需要...
易语言结合mdb数据库实现新房管理系统。源码实现了ADO方式联接,ACCESS到高级表格,ACCESS到饼形图,ACCESS到树型框,SQL分组查询,数组应用等。@易语言数据库学习教程。
易语言mdb库结构记录保存源码,mdb库结构记录保存,取mdb表名,xml表名到组合框,mdb库结构到xml,目录是否存在
Mdb字段创建Mdb字段创建Mdb字段创建
Multi-Drop Bus / Internal Communication Protocol MDB / ICP
功能:可以在arcgis软件中,利用mdb批量转gdb工具,实现批量的mdb转为gdb
新增记录新增记录时复制某一条记录的示例.mdb
mdb数据库修改器 mdb数据库修改器 mdb数据库修改器