MnesiaNote

Erlang Mnesia Database

Erlang Mnesia Doc

最近学习erlang,在erlang中天然集成了一个分布式数据库名字叫mnesia,因为数据库天然就和erlang的元组,记录无缝结合,并且具有良好的分布式特性,能够自动地在几个erlang节点上实现数据复制,效果有点像zookeeper的节点集群,
而且mnesia还支持数据库事务特性,所以mnesia在erlang应用中使用得非常频繁.

要在本地创建一个mnesia数据库,并且要实现插入,查询功能需要实现以下这几步:
1.启动erlang节点:

#erl -mnesia dir '"d://tmp//mnesia"' -sname mynode
erl -mnesia dir '"C:\Users\yafei\DevWork\Erlang\dev\mnesia\data"' -name win@27.16.194.65 -setcookie 456789
sudo erl -mnesia dir '"/data/home/data/mnesia/"' -name ali@42.96.194.60 -setcookie 456789

注意路径双引号
以上这个 “/data/home/data/mnesia/“ 目录是存放mnesia数据库的schema数据的,当然这个目录也可以不指定,那么mnesia数据库启动之后将把数据库的schema中的数据放在内存中,如果下次节点重启之后,之前数据库中创建的表结构数据就消失了.
2.接下来就是在erl shell中本地初始化一个空的 mnesia 数据库

mnesia:create_schema([node()]).

从参数上是一个节点列表,所以其实需要的话,可以在参数列表上设置多个erlang节点,就能在多个erlang节点上同时创建mnesia数据库并构成 Mnesia 集群.
3.启动mnesia数据库
初始化完成了mnesia数据库schema之后,接下来就可以启动mneisa数据库了.

mnesia:start().

至此,一个空的mneisa已经创建启动成功了,我们可以调用mnesia:info(). 查看当前mnesia数据库的一些状态,结果如下:

(ali@localhost)2> mnesia:info().
===> System info in version "4.13.2", debug level = none <===
opt_disc. Directory "/data/home/data/mnesia" is used.
use fallback at restart = true
running db nodes   = []
stopped db nodes   = [ali@localhost]
ok
(ali@localhost)3> mnesia:start().
ok
(ali@localhost)4> mnesia:info().
---> Processes holding locks <---
---> Processes waiting for locks <---
---> Participant transactions <---
---> Coordinator transactions <---
---> Uncertain transactions <---
---> Active tables <---
schema         : with 1        records occupying 408      words of mem
===> System info in version "4.13.2", debug level = none <===
opt_disc. Directory "/data/home/data/mnesia" is used.
use fallback at restart = false
running db nodes   = [ali@localhost]
stopped db nodes   = []
master node tables = []
remote             = []
ram_copies         = []
disc_copies        = [schema]
disc_only_copies   = []
[{ali@localhost,disc_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: []
ok

从 [{ali@localhost,disc_copies}] = [schema] 这行上来看当前数据库中只有一个数据库的schema表.


Mnesia 集群

分别在 阿里云 ali 和 本机 win 启动两个节点

sudo -mnesia dir '"/data/home/data/mnesia/"' -name ali@42.96.194.60 -setcookie 456789
erl -mnesia dir '"C:\Users\yafei\DevWork\Erlang\dev\mnesia\data"' -name win@27.16.194.65 -setcookie 456789

保证两个节点都启动,并且 mnesia 没有启用

mnesia:delete_schema(['win@27.16.194.65', 'ali@42.96.194.60']).
mnesia:create_schema(['win@27.16.194.65', 'ali@42.96.194.60']).

然后启动两个节点的 mnesia,查看运行详情

(win@27.16.194.65)9> mnesia:start().
(win@27.16.194.65)9> mnesia:info().
---> Processes holding locks <---
---> Processes waiting for locks <---
---> Participant transactions <---
---> Coordinator transactions <---
---> Uncertain transactions <---
---> Active tables <---
schema         : with 1        records occupying 414      words of mem
===> System info in version "4.13.2", debug level = none <===
opt_disc. Directory [99,58,47,85,115,101,114,115,47,121,97,102,101,105,47,68,
101,118,87,111,114,107,47,69,114,108,97,110,103,47,100,
101,118,47,109,110,101,115,105,97,47,85,115,101,114,115,
121,97,102,101,105,68,101,118,87,111,114,107,69,114,108,
97,110,103,127,101,118,109,110,101,115,105,97,127,97,116,
97] is used.
use fallback at restart = false
running db nodes   = ['ali@42.96.194.60','win@27.16.194.65']
stopped db nodes   = []
master node tables = []
remote             = []
ram_copies         = []
disc_copies        = [schema]
disc_only_copies   = []
[{'ali@42.96.194.60',disc_copies},{'win@27.16.194.65',disc_copies}] = [schema]
3 transactions committed, 0 aborted, 1 restarted, 2 logged to disc
0 held locks, 0 in queue; 0 local transactions, 0 remote
0 transactions waits for other nodes: []
ok

根据 running db nodes = [‘ali@42.96.194.60’,’win@27.16.194.65’] 可以看出两个节点已成功组成 节点

在任何一个节点添加数据表


erlang mnesia 数据库实现SQL查询

Mnesia是一个分布式数据库管理系统,适合于电信和其它需要持续运行和具备软实时特性的Erlang应用,越来越受关注和使用,但是目前Mnesia资料却不多,很多都只有官方的用户指南.
下面的内容将着重说明 Mnesia 数据库如何实现SQL查询,实现select / insert / update / where / order by / join / limit / delete等SQL操作.

参见示例 sql.erl

注:使用qlc模块查询,需要在文件顶部声明”-include_lib(“stdlib/include/qlc.hrl”).”,否则编译时会产生”Warning: qlc:q/1 called, but “qlc.hrl” not included”的警告.


使用单独的脚本连接 ejabberd mnesia 数据库

Cookie = 'YOUR_EJABBERD_COOKIE'. % mine was found in /var/lib/ejabberd/.erlang.cookie
EjabberdNode = 'ejabberd@127.0.0.1'. % or whatever you set as EJABBERD_NODE
erlang:set_cookie(EjabberdNode, Cookie).
net_adm:ping(EjabberdNode).
rpc:call(EjabberdNode, mnesia, system_info, [tables]).

参考 How can I connect to ejabberd’s Mnesia database with a separate script?


mnesia表数据Id自增长

1.使用函数:

mnesia:dirty_update_counter(unique_id, mine_result, 1).

2.该函数参数示意,
unique_id 表名, mine_result 表名,每次自增N.
3.
1.创建如下结构的mnesia数据库表 -record(unique_id, {item, uid}),该表是为了存储 mine_result 表的最大的Id值;
2.每为 mine_result 表加入一条新记录时,需要得到新的id值:

mnesia:dirty_update_counter(unique_id,  mine_result , 1),

从unique_id表中取出最大的Id值加1,更新unique_id表的数据,返回最大Id值加1,
注意:请在建立unique_id表的时候,往里面插入数据;表名,初始值,{ mine_result ,0},
我做了一个实验如果unique_id表中没有数据的时候,并发向mine_result库中插入100条数据时,不稳定.
但是unique_id表中加入一个数据后,并发数提高到30000,还是很稳定.


参考
wudaijun’s blog - Erlang mnesia
创设Mnesia数据库
Erlang的Mnesia——为高伸缩性应用准备的数据库管理系统
[Erlang-0008][OTP] 高效指南 – 表和数据库(ets mnesia)
Erlang基础Mnesia 之应用场景
erlang Mnesia - 尚待研究

mnesia数据库使用体验
mnesia数据库优化

文章目录
  1. 1. Erlang Mnesia Database
    1. 1.1. Mnesia 集群
    2. 1.2. erlang mnesia 数据库实现SQL查询
    3. 1.3. 使用单独的脚本连接 ejabberd mnesia 数据库
    4. 1.4. mnesia表数据Id自增长