資料庫讀寫鎖的實現(C++)

來源:互聯網
上載者:User

一、基本概念

在資料庫中,對某資料的兩個基本操作為寫和讀,分布有兩種鎖控制:排它鎖(X鎖)、共用鎖定(S鎖)。

排它鎖(x鎖):若事務T對資料D加X鎖,則其它任何事務都不能再對D加任何類型的鎖,直至T釋放D上的X鎖;

                 一般要求在修改資料前要向該資料加排它鎖,所以排它鎖又稱為寫鎖。

共用鎖定(s鎖):若事務T對資料D加S鎖,則其它事務只能對D加S鎖,而不能加X鎖,直至T釋放D上的S鎖;

                一般要求在讀取資料前要向該資料加共用鎖定, 所以共用鎖定又稱讀鎖。

程式所收到的請求包括以下五種:Start、End、XLock、SLock、Unlock

Start:開啟相應的事件請求

End:  關閉相應的事件請求

XLock: 對資料對象D添加X鎖,進行寫操作(當事件以對資料A加入S鎖時,此時可升級為X鎖)

SLock: 對資料對象D添加S鎖,進行讀操作

Unlock: 對資料對象D進行解鎖(對資料D的X/S鎖解除綁定,並檢查等待隊列)

本程式並不進行死結檢測以及死結預防,對於等待隊列採取FIFO原則進行。

二、資料結構

讀寫鎖維護一個資料D的狀態表,標記當前資料D的即時狀態,鎖表的資訊隨著事務的執行動態更新,反映當前的鎖狀態。

其資料結構如所示:


其中:mObjectList:為map結構的對象樹,可方便快速尋找相應對象。

        objectName:為對象資料D的名稱

        curXLockTrans: 為當前寫操作的事件

        waitingTransList: 為寫等待隊列

        shareList: 為共用集(當curXLockTrans不為空白時,變為共用等待隊列)

事件ID的資料結構如下:


其中:mTransId: 為map結構的事件樹,可以快速的尋找相應事件

     tranId: 為事件名稱

        curLockObjList: 為此事件目前所操作的對象列表

三、原始碼

本程式為所的鎖管理介面,所以封裝成類,方便程式調用。程式源碼可以點擊這裡下載。

資料結構如下:

class LMer {private:     struct object    {        string objectName;        string curXLockTrans;        queue<string> waitingTransList;        set<string> shareList;    };    struct transId    {        string   tranId;        set<object*>  curLockObjList;    };    map<string, object*> mObjectList;     map<string, transId*> mTransId;public:        LMer(){}    string LMer::handleInput(vector<string>& vInput);    void LMer::handleAction(string sAction, transId* trId, object* obj, string& result);    void LMer::diviTransID(transId* trId, object* pObj, string& result);};
邏輯結構實現如下:

string LMer::handleInput(vector<string>& vInput){    string result = "";    //二參數輸入    if (vInput.size() == 2)    {    //進程存在,進入下一步        map<string, transId*>::iterator transIt = mTransId.find(vInput[1]);        if (transIt != mTransId.end())        {            //是否結束事件(結束事件隊列中所有事件)            if (vInput[0] == "End")            {                result += "\tTransaction "+ vInput[1] +" ended\n\t\t\t";                //解除綁定進程所有事物                set<object*>::iterator obj_index;                while(transIt->second->curLockObjList.size() != 0)                {                    obj_index = transIt->second->curLockObjList.begin();                    diviTransID(transIt->second, *obj_index, result);                }                //清空請求事件                mTransId.erase(transIt);            }        }        else if(vInput[0] == "Start")//為start,創立進程        {            transId* pTransId = new transId();            pTransId->tranId = vInput[1];            //將此進程加入進程樹中            mTransId[vInput[1]] = pTransId;            result += "Transaction " + vInput[1] +" started\n";        }    }    else //三參數輸入     {    //建立新操作對象        if(mObjectList.find(vInput[2]) == mObjectList.end())        {            object* pObjectIndex = new object();            pObjectIndex->objectName = vInput[2];            pObjectIndex->curXLockTrans = "";            mObjectList[vInput[2]] = pObjectIndex;        }        if (vInput[0] == "Unlock")        {            //解鎖trans->obj            diviTransID(mTransId[vInput[1]], mObjectList[vInput[2]], result);        }        else//進行常規處理(Xlock、Slock)        {            //進行處理            handleAction(vInput[0], mTransId[vInput[1]], mObjectList[vInput[2]], result);        }    }    return result;}void LMer::handleAction(string sAction, transId* trId, object* obj, string& result){    //檢查是否有佔用    if (sAction == "SLock")    {        if (obj->curXLockTrans == "")        {            obj->shareList.insert(trId->tranId);            trId->curLockObjList.insert(obj);            result += "S-Lock granted to "+ trId->tranId +"\n";        }        else//被佔用        {            obj->shareList.insert(trId->tranId);            result += "Waiting for lock (X-lock held by: "+ obj->curXLockTrans +")\n";        }    }    else if(sAction == "XLock")    {        //未有寫操作        if (obj->curXLockTrans == "")        {            int shareNum = obj->shareList.size();            if (shareNum > 1)            {                string sTemp = "";                for (set<string>::iterator it_index = obj->shareList.begin();                    it_index != obj->shareList.end(); it_index++)                {                    sTemp += " " + *it_index;                }                obj->waitingTransList.push(trId->tranId);                result += "Waiting for lock (S-lock held by:" + sTemp + "\n";            }            else if (shareNum == 1)            {                //update                if (*(obj->shareList.begin()) == trId->tranId)                {                    obj->curXLockTrans = trId->tranId;                    obj->shareList.clear();                    result += "Upgrade to XLock granted\n";                }                else                {                    obj->waitingTransList.push(trId->tranId);                    result += "Waiting for lock (S-lock held by:" + *(obj->shareList.begin()) + ")\n";                }            }            else if (shareNum == 0)            {                obj->curXLockTrans = trId->tranId;                trId->curLockObjList.insert(obj);                result += "XLock granted\n";            }        }        else//當前存在寫操作        {            obj->waitingTransList.push(trId->tranId);            result += "Waiting for lock (X-lock held by: "+ obj->curXLockTrans +")\n";        }    }}void LMer::diviTransID(transId* trId, object* pObj, string& result){    if(pObj->curXLockTrans != "")    {        //對寫操作解除綁定        if (pObj->curXLockTrans == trId->tranId)        {            pObj->curXLockTrans = "";            trId->curLockObjList.erase(pObj);            result += "Lock released\n\t\t\t";        }        else        {            result += "I can not find the transaction.\n\t\t\t";        }    }//對共用讀集合解除綁定    else     {        set<string>::iterator shareIndex = pObj->shareList.find(trId->tranId);        if (shareIndex != pObj->shareList.end())        {            pObj->shareList.erase(shareIndex);            trId->curLockObjList.erase(pObj);            result += "Lock released\n\t\t\t";        }        else        {            result += "I can not find the transaction.\n\t\t\t";        }    }    //查看寫等待隊列    if (pObj->waitingTransList.size() != 0)    {        pObj->curXLockTrans = pObj->waitingTransList.front();        pObj->waitingTransList.pop();        result += "X-Lock on "+ pObj->objectName +" granted to "+ pObj->curXLockTrans +"\n";    }//查看共用隊列    else if (pObj->shareList.size() != 0)    {        string temp = "";        for(set<string>::iterator it_index = pObj->shareList.begin();            it_index != pObj->shareList.end(); it_index++)        {            temp += " " + *it_index;        }        result += "S-Lock on "+ pObj->objectName +" granted to "+ temp +"\n";    }}

四、程式運行

程式資料輸入如下:



運行後得到結果如下:




相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.