zoukankan      html  css  js  c++  java
  • erlang mnesia数据库简单应用

    mnesia是erlang自带的分布式数据库,基于ets和dets实现的。mnesia兼顾了dets的持久性和ets的高性能,可以自动在多个erlang节点间同步数据库。最关键的是,mnesia实现了事务机制。

    mnesia数据库有一个schema表,保存着数据库相关的一些信息,例如如何将表保存到磁盘、如何加载这些表、在哪些节点间同步数据。构建集群,关键是处理这个schema表。

    调用函数mnesia:create_schema(ListOfNodes)可以创建schema,这必须在启动mnesia之前调用。缺省情况下,schema会保存在节点启动的当前目录,可以在应用启动时修改这个参数erl -name SomeName -mnesia dir where/to/store/table,或者执行函数application:set_env(mnesia, dir, "where/to/store/table").

    初始化时构建mnesia集群

    必须保证每一个Node都没有schema,如果有,调用mnesia:delete_schema删除。

    在本地启动两个erlang 节点:

    erl -name a@127.0.0.1 -mnesia dir '"path1"' -s mnesia
    erl -name b@127.0.0.1 -mnesia dir '"path2"' -s mnesia
    

    mnesia启动后会创建schema的,所以需要先删除schema,再重新创建。

    (a@127.0.0.1)1> mnesia:system_info().
    ===> System info in version "4.11", debug level = none <===
    opt_disc. Directory "path1" is NOT used.
    use fallback at restart = false
    running db nodes   = ['a@127.0.0.1']
    stopped db nodes   = []
    master node tables = []
    remote             = []
    ram_copies         = [schema]
    disc_copies        = []
    disc_only_copies   = []
    [{'a@127.0.0.1',ram_copies}] = [schema]
    2 transactions committed, 0 aborted, 0 restarted, 0 logged to disc
    0 held locks, 0 in queue; 0 local transactions, 0 remote
    0 transactions waits for other nodes: []
    
    (b@127.0.0.1)1> mnesia:system_info().
    ===> System info in version "4.11", debug level = none <===
    opt_disc. Directory "path2" is NOT used.
    use fallback at restart = false
    running db nodes   = ['b@127.0.0.1']
    stopped db nodes   = []
    master node tables = []
    remote             = []
    ram_copies         = [schema]
    disc_copies        = []
    disc_only_copies   = []
    [{'b@127.0.0.1',ram_copies}] = [schema]
    2 transactions committed, 0 aborted, 0 restarted, 0 logged to disc
    0 held locks, 0 in queue; 0 local transactions, 0 remote
    0 transactions waits for other nodes: []
    

    分别在两个节点上运行下面的命令删除schema

    mnesia:stop(),
    mnesia:delete_schema([node()])
    

    在任意一个节点上(选择的是a@127.0.0.1)运行创建schema

    mnesia:create_schema([node(), 'b@127.0.0.1']).
    

    之后就可以看到在两个节点上看到新的schema了

    (a@127.0.0.1)7> mnesia:system_info().
    ===> System info in version "4.11", debug level = none <===
    opt_disc. Directory "/Users/zhaoxiaosen/work" is used.
    use fallback at restart = true
    running db nodes   = []
    stopped db nodes   = ['b@127.0.0.1','a@127.0.0.1']
    
    (b@127.0.0.1)5> mnesia:system_info().
    ===> System info in version "4.11", debug level = none <===
    opt_disc. Directory "/Users/zhaoxiaosen" is used.
    use fallback at restart = true
    running db nodes   = []
    stopped db nodes   = ['b@127.0.0.1','a@127.0.0.1']
    

    最后分别启动mnesia。

    给已有的mnesia集群添加node

    新启动一个节点c@127.0.0.1

    erl -name c@127.0.0.1 -mnesia dir '"path3"' -s mnesia
    
    1. 在a节点上运行mnesia:change_config(extra_db_nodes, ['c@127.0.0.1']).,将c节点连接到集群上,这时,c只是复制了schema
    2. 在c节点上更改存储方式,mnesia:change_table_copy_type(schema, 'c@127.0.0.1', disc_copies).
    3. 将所有表都同步到c节点上
    [{Tb, mnesia:add_table_copy(Tb, node(), Type)}
     || {Tb, [{'a@node', Type}]} <- [{T, mnesia:table_info(T, where_to_commit)}
                                   || T <- mnesia:system_info(tables)]].
    

    这样,新的节点就加入到mnesia集群上了。

    上面的例子中,在启动节点时启动了mnesia,主要是为了测试删除schema

    实例代码

    %%启动
    init_once() ->
        mnesia:stop(),
        mnesia:create_schema([node()]),
        mnesia:start(),
        mnesia:create_table(tab1, [{disc_copies, [node()]},
                                     {attributes, record_info(fields, config)}]),
        mnesia:create_table(tab2, [{ram_copies, [node()]},
                                      {attributes, record_info(fields, watcher)}]),
        mnesia:create_table(tab3, [{ram_copies, [node()]},
                                      {attributes, record_info(fields, version)}]).
    %%更改存储方式
    change_table_copy_type([]) ->
        ok;
    change_table_copy_type([Node | T]) ->
        mnesia:change_table_copy_type(schema, Node, disc_copies),
        mnesia:change_table_copy_type(tab1, Node, disc_copies),
        mnesia:change_table_copy_type(tab2, Node, ram_copies),
        mnesia:change_table_copy_type(tab3, Node, ram_copies),
        change_table_copy_type(T).
    %%集群添加节点
    sync_data(Node) when is_atom(Node) ->
        sync_data([Node]);
    sync_data(Nodes) when is_list(Nodes) ->
        mnesia:change_config(extra_db_nodes, Nodes),
        change_table_copy_type(Nodes),
        add_table_copy(Nodes);
    sync_data(_) ->
        ok.
    %%同步数据
    add_table_copy([]) ->
        ok;
    add_table_copy([Node | T]) ->
        [mnesia:add_table_copy(Tb, Node, Type)
          || {Tb, [{_, Type}]} <- [{T1, mnesia:table_info(T1, where_to_commit)}
                                           || T1 <- mnesia:system_info(tables)]],
        add_table_copy(T).
    %%事务执行,Q为操作命令
    do(Q) ->
        F = fun() -> qlc:e(Q) end,
        mnesia:transaction(F).
    

    其它常用函数

    wait_for_tables(TabList, Timeout) -> ok | {timeout, BadTabList} | {error, Reason}
    

    Some applications need to wait for certain tables to be accessible to do useful work. mnesia:wait_for_tables/2 either hangs until all tables in TabList are accessible, or until timeout is reached.

  • 相关阅读:
    Web前端笔记和简历模板
    三种 Loading 制作方案
    注册中心之健康检测机制
    HTTPS与加密
    多线程-JUC
    date日期类型
    spring配置文件约束
    Tomcat web.xml 中的listener、 filter、servlet 加载顺序
    java 日志框架总结
    mysql常用命令
  • 原文地址:https://www.cnblogs.com/xianzhedeyu/p/5881677.html
Copyright © 2011-2022 走看看