內存數據庫研發日誌之一.共享內存的詭異問題

內存數據庫研發日誌之一.共享內存的詭異問題

草木瓜

20091211


一、序

數據庫在應用系統中非常複雜的,以Oracle數據庫爲例,其複雜度不亞於任何
操作系統。自已動手寫個內存數據庫,簡直就是天方夜譚。但這次我非要譚一
譚,開發一個內存數據庫。不僅包括後臺控制調用部分(考慮用C/C++實現),
而且還準備寫一個WebConsole(考慮用Java實現)。

話還沒說完,這個數據庫功能要簡單而且實用,性能要十分出色,這就是目標,
不是說要把Oracle之類打倒,那反而是癡人說夢,給你30年也搞不定。至於要
多少時間實現,只能說是慢慢來,因爲只是打算利用業餘時間。

這方面內容先前其實就有所準備,不過寫了一個非常不象樣的東西,比Oracle
第一個版本還要不象樣!想了下,這個版本,命名爲2.0,這個似乎有點象Oracle,
因爲它賣給用戶的第一個版本就是2.0。

 

二、共享內存

還是與Oracle一樣,使用共享內存存放數據庫數據。不過今天測試偶然發現了
一個問題,共享內存部分不能共享。問題就在於這個“部分”!

現象描述:

1. 啓動內存測試程序

[oracle@windows memdb2] ./testtablevar 123
[ERR] Memory::Open: No such file or directory
  Size,    Max,    Hwm, HeadSize,   Free, Reused,   Used
------------------------------------------------------------
10000000,   2441,      1,    58644,      1,      0,      0
    ID,    Key,   Hash,  Start,    Len,    Pre,   Next
------------------------------------------------------------
     0,      0,      0,      0,      0,      0,      0
     1,      0,      0,      1,   2441,      0,      0
C>
顯示如上內容,這裏其實已經創建了共享內存:

2. 查看Linux下共享內存信息

[oracle@windows memdb2] ipcs
------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status     
0x00000123 524288     oracle    640        500000000  0      

3. 重新運行程序

[oracle@windows memdb2]$ ./testtablevar 123
  Size,    Max,    Hwm, HeadSize,   Free, Reused,   Used
------------------------------------------------------------
10000000,   2441,      1,    58644,      1,      0,      0
    ID,    Key,   Hash,  Start,    Len,    Pre,   Next
------------------------------------------------------------
     0,      0,      0,      0,      0,      0,      0
     1,      0,      0,      0,      0,      0,      0
C>
注意,部分內存信息丟失。

There  is  currently no intrinsic way for a process to ensure exclusive
access to a  shared  memory  segment.   Asserting  both  IPC_CREAT  and
IPC_EXCL  in  shmflg only ensures (on success) that a new shared memory
segment will be created, it doesn’t imply exclusive access to the  seg-
ment.

奇怪吧~

4.在上面這個界面不退出,直接輸入命令r,p,q

C>r
C>p
    ID,    Key,   Hash,  Start,    Len,    Pre,   Next
------------------------------------------------------------
     0,      0,      0,      0,      0,      0,      0
     1,      0,      0,      1,   2441,      0,      0
C>q

r作用是重新初始化內存(不調用任何內存Call,只是邏輯處理),p打印信息
    
5.再重新運行程序

[oracle@windows memdb2]$ ./testtablevar 123
  Size,    Max,    Hwm, HeadSize,   Free, Reused,   Used
------------------------------------------------------------
10000000,   2441,      1,    58644,      1,      0,      0
    ID,    Key,   Hash,  Start,    Len,    Pre,   Next
------------------------------------------------------------
     0,      0,      0,      0,      0,      0,      0
     1,      0,      0,      1,   2441,      0,      0
C>

一切正常,換一個程序查詢內存,還是沒問題!


6.問題原因

剛寫到這裏,突然知道問題所在了,就是內存地址的問題!每次打開共享
內存時一定要重新設置所有指針!

void TableVar::Open(void * _addr) {

 this->m_pHead = (TTableVarHead *)_addr;

}

須改爲

void TableVar::Open(void * _addr) {

 this->m_pHead = (TTableVarHead *)_addr;
 
 this->m_pHead->data = (char *)_addr + this->m_pHead->headsize ;
 this->m_pHead->chain = (TTableVarHeadChain *)( (char *)this->m_pHead + sizeof(TTableVarHead) );
 
}

所有的內存表類都所在這個問題!仔細回顧一下,上次不象樣的程序好象
也出過類似問題,及時寫好日誌是個非常好的辦法,害得我搞了半天!


三、後記

研發道路一定佈滿荊棘,但問題關鍵在於總結與記錄,去不斷豐富個人的
設計思想,擴展軟件知識面。最終獲得一定遠比一個不象樣的數據庫要多
得多。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章