mnesia数据库学习笔记四
雜項(xiàng)
前二章講了如何啟動數(shù)據(jù)庫,如何構(gòu)建數(shù)據(jù)庫,接下來會為講一些創(chuàng)建分布式容錯數(shù)據(jù)所需的高級特征:
- 索引
- 分布式和容錯
- 表分段
- 本地內(nèi)容表
- 無磁盤節(jié)點(diǎn)
- 高級方案管理
- 調(diào)用應(yīng)用程序
- 并行進(jìn)程
- 原形研究
- 基于對象的編程
1、索引
如果數(shù)據(jù)添加索引,那位定位會很快,如果沒有索引,就需要遍歷表,可能會消耗較長時間。Mnesia提供了如下兩個函數(shù)操作索引:
mnesia:add_table_index(Tab, AttributeName)
mnesia:delete_table_index(Tab,AttributeName)
可能通過如下函數(shù)進(jìn)行索引查找:
mnesia:index_read(Tab, SecondaryKey, AttributeName) mnesia:index_match_object(Pattern, AttributeName) mnesia:match_object(Pattern)’
2、分布式和容錯
mnesia提供了多種方式把表復(fù)制到多個不同的Erlang節(jié)點(diǎn)上。編程人員除表名不用關(guān)心表的具體在那個節(jié)點(diǎn)上。實(shí)現(xiàn)具體位置透明化。(當(dāng)然如果數(shù)據(jù)在遠(yuǎn)程節(jié)點(diǎn),處理會慢一點(diǎn)), 數(shù)據(jù)庫可以反復(fù)配置, 表可以在節(jié)點(diǎn)間移動。這并不影響編程人員。
以下是創(chuàng)建一個表,帶有兩個復(fù)件:
??? mnesia:create_table(foo,
??????????????????????? [{ram_copies, [N1, N2]},
???????????????????????? {attributes, record_info(fields, foo)}]).
?
表可能擁有如下類型,每個類型都可以有一個Erlang節(jié)點(diǎn)列表:
ram_copies,RAM復(fù)件會在每個節(jié)點(diǎn)上存在。可以通過mnesia:dump_table函數(shù)將RAM表保存到磁盤上。
disc_copies,表復(fù)件會在每個節(jié)點(diǎn)的內(nèi)存和磁盤上存在。寫操作會影響RAM和磁盤。
disc_only_copies,表復(fù)件只會出在各節(jié)點(diǎn)的磁盤上。會影響訪問速度,但會節(jié)約內(nèi)存。
運(yùn)行時也是可以修改表屬性的。使用表復(fù)件有兩個原因, 容錯和速度。如果我們擁有兩個活動節(jié)點(diǎn), 任一節(jié)點(diǎn)故障后,復(fù)件節(jié)點(diǎn)仍然可用。 此外,假如一個表存在兩個節(jié)點(diǎn),應(yīng)用程序在任一節(jié)點(diǎn)上讀數(shù)據(jù)而無需訪問網(wǎng)絡(luò)。網(wǎng)絡(luò)訪問意味著比本地操作低效。
對于數(shù)據(jù)經(jīng)常讀,而少量寫的應(yīng)用,表復(fù)件是非常具有優(yōu)勢的。劣勢就是增加了寫操作時間。假如一個表有兩個復(fù)件,每一個寫操作必需訪問兩個表復(fù)件。甚至其中一個寫操作為網(wǎng)絡(luò)操作。消耗比非復(fù)件表大很多。
3、表片段
?表片段主用于應(yīng)對超大表。其核心就是把一個表分隔成多個可控表片段。每個片段被實(shí)現(xiàn)為第一級的Mnesia表,就像普通表一樣,可以復(fù)件,可以索引等。但是不能擁有l(wèi)ocal_content和snmp活動連接。
mnesia提供了mnesia_frag模塊, 實(shí)現(xiàn)了mnesia_access回調(diào)行為用于訪問片該記錄。
在訪問記錄前,mnesia_frag先計算記錄鍵值的hash值 ,然后通過hash值確定表片段名字。最終就像普通表一樣進(jìn)行訪問處理。如果不能預(yù)先知道記錄鍵值, 需要在所有表片段中進(jìn)行匹配。注,在ordered_set表中,記錄在表片段內(nèi)進(jìn)行排序。select 和match_object等函數(shù)的返回結(jié)果也是無序的。如下就是展示了如何將一個現(xiàn)存表轉(zhuǎn)換成片段表,如何添加更多表片段。
?
Eshell V4.7.3.3? (abort with ^G)(a@sam)1> mnesia:start().
ok
(a@sam)2> mnesia:system_info(running_db_nodes).
[b@sam,c@sam,a@sam]
(a@sam)3> Tab = dictionary.
dictionary
(a@sam)4> mnesia:create_table(Tab, [{ram_copies, [a@sam, b@sam]}]).
{atomic,ok}
(a@sam)5> Write = fun(Keys) -> [mnesia:write({Tab,K,-K}) || K <- Keys], ok end.
#Fun<erl_eval>
(a@sam)6> mnesia:activity(sync_dirty, Write, [lists:seq(1, 256)], mnesia_frag).
ok
(a@sam)7> mnesia:change_table_frag(Tab, {activate, []}).
{atomic,ok}
(a@sam)8> mnesia:table_info(Tab, frag_properties).
[{base_table,dictionary},
?{foreign_key,undefined},
?{n_doubles,0},
?{n_fragments,1},
?{next_n_to_split,1},
?{node_pool,[a@sam,b@sam,c@sam]}]
(a@sam)9> Info = fun(Item) -> mnesia:table_info(Tab, Item) end.
#Fun<erl_eval>
(a@sam)10> Dist = mnesia:activity(sync_dirty, Info, [frag_dist], mnesia_frag).
[{c@sam,0},{a@sam,1},{b@sam,1}]
(a@sam)11> mnesia:change_table_frag(Tab, {add_frag, Dist}).
{atomic,ok}
(a@sam)12> Dist2 = mnesia:activity(sync_dirty, Info, [frag_dist], mnesia_frag).
[{b@sam,1},{c@sam,1},{a@sam,2}]
(a@sam)13> mnesia:change_table_frag(Tab, {add_frag, Dist2}).
{atomic,ok}
(a@sam)14> Dist3 = mnesia:activity(sync_dirty, Info, [frag_dist], mnesia_frag).
[{a@sam,2},{b@sam,2},{c@sam,2}]
(a@sam)15> mnesia:change_table_frag(Tab, {add_frag, Dist3}).
{atomic,ok}
(a@sam)16> Read = fun(Key) -> mnesia:read({Tab, Key}) end.
#Fun<erl_eval>
(a@sam)17> mnesia:activity(transaction, Read, [12], mnesia_frag).
[{dictionary,12,-12}]
(a@sam)18> mnesia:activity(sync_dirty, Info, [frag_size], mnesia_frag).
[{dictionary,64},
?{dictionary_frag2,64},
?{dictionary_frag3,64},
?{dictionary_frag4,64}]
(a@sam)19>?
?表片段屬性
可以能過mnesia:table_info(Tab, frag_properties).取得表性能, 其中有如下屬性:
{n_fragments, Int}表上有多少片段
{node_pool, List}
{n_ram_copies, Int}
{n_disc_only_copies, Int}
{foreign_key, ForeignKey}
{hash_module, Atom}
表片段管理
?mnesia:change_table_frag(Tab,? Change)? 用作重新配置片段表。可以有如下參數(shù):
?{activate, FragProps}激活現(xiàn)存表的片段屬性
deactivate? 停止片段屬性
{add_frag, NodesOrDist}添加一個新片段
del_frag刪除 一個片段
{add_node, Node}添加一個新節(jié)點(diǎn)到節(jié)點(diǎn)池。
{del_node, Node}從節(jié)點(diǎn)池刪除一節(jié)點(diǎn)
擴(kuò)展憶存在的函數(shù)
函數(shù)?mnesia:create_table/2 通過指定?frag_properties 屬性創(chuàng)建片段表。
?mnesia:delete_table/1 刪除片段表,并刪除所有片段。
??mnesia:table_info/2能夠取出所有frag_properties 項(xiàng)目。
負(fù)載平衡
在做負(fù)載平衡可能要注意以下情況:
節(jié)點(diǎn)發(fā)生永久變化, 如節(jié)點(diǎn)添加或者移除,此時可能要變化節(jié)點(diǎn)池。也可能引起表片段發(fā)生變化,進(jìn)行重新分配。
內(nèi)存使用超過閥值,此時也許要重新考慮添加表片段等。
臨時節(jié)點(diǎn)故障,這種情可能可能需要添加些復(fù)件,用于冗余 。
4、本地內(nèi)容表
復(fù)件表擁有相同內(nèi)容在所有節(jié)點(diǎn)上,有時要可能需要各個節(jié)點(diǎn)保存不一樣的數(shù)據(jù)。當(dāng)我們創(chuàng)建表時指定屬性{local_content, true},表存在于我們指定的節(jié)點(diǎn)上存在, 所有操作僅在本地備份上。另外,我們在啟動時,只初始化本地版本,不會與會遠(yuǎn)端節(jié)點(diǎn)進(jìn)行同步。
5、無磁盤節(jié)點(diǎn)
?可以在無磁盤節(jié)點(diǎn)上運(yùn)行mnesia, 當(dāng)然不能在這些節(jié)點(diǎn)上運(yùn)行disc_copies,disc_only_copies類型的節(jié)點(diǎn), 所有mnesia啟動自己需要的schema表會比較麻煩。
shema表像其它表一樣,存在于一個或多個節(jié)點(diǎn)上,它的存儲類型是disc_copies或者ram_copies(不可為disc_only_copies).在啟動mnesia方案的時候,確定了哪些節(jié)點(diǎn)需要建立聯(lián)系,如果有任何其它節(jié)點(diǎn)已經(jīng)啟動了,就從已經(jīng)已經(jīng)啟動了節(jié)點(diǎn)取得表定義與本地的進(jìn)行合并。參數(shù)extra_db_nodes就是用于指定節(jié)點(diǎn)列表。
所以,當(dāng)一個無磁盤節(jié)點(diǎn)需要從網(wǎng)絡(luò)的遠(yuǎn)端節(jié)點(diǎn)上找到一個方案定義 , 我們應(yīng)該提供節(jié)點(diǎn)列表信息,參數(shù)如:-mnesia extra_db_nodes NodeList。對于沒有進(jìn)行配置指定的, mnesia會作為一個單節(jié)點(diǎn)系統(tǒng)啟動, 也可以通過使用mnesia:change_config/2重置'extra_db_nodes',強(qiáng)制連接。
6、更多方案管理
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/freebird92/archive/2011/12/26/2298195.html
總結(jié)
以上是生活随笔為你收集整理的mnesia数据库学习笔记四的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UDPRouter
- 下一篇: linux下测试RTC驱动相关的命令da