日期:2014-05-16  浏览次数:20358 次

Erlang------Mnesia
读erlang编程指南Mnesia笔记:
1.mnesia 是ets和dets上面封装一层的事务层。底层实现用的是这,重点加强了锁和分布式的适应。

2.不应使用mnesia的场合:
2.1 简单的键-值查询;--------最好用ets或dict
巨大的二进制数据:图片,音频;--------把每个记录和文件脱离,只记录文件名之类。(好像还有个开源数据库可用的?)2.2 一个持续的日志;----------disk_log库
2.3 一个必须存储GB级别的数据库;--------这个不是首选,但是可以用来[/color]缓存用户会话(在线)数据,定时写入到指定数据库中。
2.4 一直增长的大型数据档案。

3.Mnesia封装成一个OTP的[color=red]应用程序
,要创建一个空模式并存在磁盘或内存上以启动它,有了模式才会有表。
create_schema(DiscNodes) -> ok | {error,Reason}

application:start(mnesia).-----------在应用时要先启动,也可用mnesia:start().
create_table(Name, TabDef) -> {atomic, ok} | {aborted, Reason

4.小技巧:要知道一个节点ping通么:net_adm:pin(Nodes).->pong |pang
    node()返回本节点名,nodes()返回所有其它节点名。

5.一个项目中有多个应用程序,这些应用程序是平行的,如果这里有时序问题(即要求加载完某些表再运行这个应用程序时,要在些进程中使用(特别是大量数据要加载时)
wait_for_tables(TabList,Timeout) -> ok | {timeout, BadTabList} | {error, Reason}
Some applications need to wait for certain tables to be accessible in order to do useful work. mnesia:wait_for_tables/2 hangs until all tables in the TabList are accessible, or until timeout is reached.
如果是{timeout,Tablelist}----->则忽略,假定他们已加载吧。

6.事务处理
transaction(Fun [[, Args], Retries]) -> {aborted, Reason} | {atomic, ResultOfFun}

This function executes the functional object Fun with arguments Args as a transaction.
The code which executes inside the transaction can consist of a series of table manipulation functions. If something goes wrong inside the transaction as a result of a user error or a certain table not being available, the entire transaction is aborted and the function transaction/1 returns the tuple {aborted, Reason}.
If all is well, {atomic, ResultOfFun} is returned where ResultOfFun is the value of the last expression in Fun.
A function which adds a family to the database can be written as follows if we have a structure {family, Father, Mother, ChildrenList}:
add_family({family, F, M, Children}) ->
    ChildOids = lists:map(fun oid/1, Children),
    Trans = fun() ->      
        mnesia:write(F#person{children = ChildOids}, 
        mnesia:write(M#person{children = ChildOids},
        Write = fun(Child) -> mnesia:write(Child) end,
        lists:foreach(Write, Children)
    end,
    mnesia:transaction(Trans).

oid(Rec) -> {element(1, Rec), element(2, Rec)}.
       

This code adds a set of people to the database. Running this code within one transaction will ensure that either the whole family is added to the database, or the whole transaction aborts. For example, if the last child is badly formatted, or the executing process terminates due to an 'EXIT' signal while executing the family code, the transaction aborts. Accordingly, the situation where half a family is added can never occur.
It is also useful to update the database within a transaction if several processes concurrently update the same records. For example, the function raise(Name, Amount), which adds Amount to the salary field of a person, should be implemented as follows:
以自己主动调用abort/2来终止事务的情况
raise(Name, Amount) ->
    mnesia:transaction(fun() ->
        case mnesia:wread({person, Name}) of
            [P] ->
                Salary = Amount + P#person.salary,
                P2 = P#person{salary = Salary},
                mnesia:write(P2);
            _ ->
                mnesia:abort("No such person")
        end
    end).

When this function executes within a transaction, several processes running on different nodes can concurrently execute the raise/2 function w