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 without interfering with each other.
死锁会终止后重试
Since Mnesia detects deadlocks, a transaction can be restarted any number of times. This function will attempt a restart as specified in Retries. Retries must be an integer greater than 0 or the atom infinity. Default is infinity.

防止边界操作
即不在要在事务里面执行无法撤消的操作(如发消息,io:format/2).

7.数据的读写,删, 备份?to_do
8.数据的脏(dirty)读写,删,更新
这个drity比事务中平均快10倍哦。为了保证数据的一致性:
对于不是分布式的:只在单一的进程去序列化所有的破坏性操作(写,更新)其它进程只是查询类(如果要改变,发消息到这个进程来做,给个接口给外部)
对于分布式:如果还是采用上面的方法用一个节点去序列化,则会负载过大,所以要会开,如偶数键的在一个节点上,奇数键的在另一个节点上来平分压力;
另外还有执行破坏操作时网络断了怎么办?数据就不一致了:
这个在脏操作中是无法避免的,那么事务操作时会发生这种情况么?
会,假定两个节点在副本上各自更新时,网络故障,二个表不一致则:用
set_master_nodes(Tab, MasterNodes[/color)] -> ok | {error, Reason}来设置主节点,如果网络分区,那么mnesia会自动把主节点上的内容同步复制下去并复制回来,所有分节点不在主节点上更新的都会被丢弃。所以考虑主节点的重要性!!!!

9.表的遍历:
first/1 ----next/2
select
match
foldl

10.在工业系统级别的应用中,还有[color=red]表分段,备份,故障恢复,Mnesia事件和无盘节点。还在去看去找!!!!!to_do.



11.erlang doc里面的内容:
Mnesia is A Distributed Telecommunications DBMS 强于分布式。

Mnesia privide:
1. A relational/object hybrid data model which is suitable for telecommunications applications.----可兼容多种适合电信业务的数据类型。
2.  A specifically designed DBMS query language, QLC (as an add-on library).
3. Persistence. Tables may be coherently kept on disc as well as in main memory.可存于磁盘,内存,或两者都有的。
4.Replication. Tables may be replicated at several nodes.几个节点共享,为分布式而生的。
5.Atomic transactions. A series of table manipulation operations can be grouped into a single atomic transaction.事务处理
6.Location transparency. Programs can be written without knowledge of the actual location of data.
7.Extremely fast real time data searches.快
8.Schema manipulation routines. It is possible to reconfigure the DBMS at runtime without stopping the system. 热更新,不用停机。
These copies can be dumped to disc at regular intervals. However, updates to these copies are not written to disc on a transaction basis.所有的数据在内存中有一定间隔的入到磁盘中(可设置时间),便是更新这些不是在事务中的。

mnesia:add_table_index(person, age)
可以给一个table加多个index相当于key,不过会使空间变大且插入变慢。

Note:It is more than 10 times more efficient to read records dirty than within a transaction.

Note: currently 'ordered_set' is not supported for 'disc_only_copies'.

delete/3 delete_object/3的区别:If a table is of type bag, we may sometimes want to delete only some of the records with a certain key. This can be done with the delete_object/3 function. A complete record must be supplied to this function.


http://shiningray.cn/docs/mnesia-a-distributed-robust-dbms-for-telecommunications-applications
Erlang------Mnesia_第1张图片

  • Erlang------Mnesia_第2张图片
  • 大小: 71.1 KB
  • 查看图片附件

你可能感兴趣的:(erlang,mnesia)