Mnesia(8)

2019-01-12 11:40

这些方法使用Fun方法来对每条record迭代Tab表

Fun有两个参数,第一个是表的一条记录,第二个参数是accumulator,返回值是一个新的accumulator

如找出所有salary小于10的employee:

Java代码

?? find_low_salaries() -> ?? Constraint =

?? fun(Emp, Acc) when Emp#employee.salary < 10 -> ?? [Emp | Acc]; ?? (_, Acc) -> ?? Acc ?? end,

?? Find = fun() -> mnesia:foldl(Contraint, [], employee) end, ?? mnesia:transaction(Find).

find_low_salaries() -> Constraint =

fun(Emp, Acc) when Emp#employee.salary < 10 -> [Emp | Acc]; (_, Acc) -> Acc end,

Find = fun() -> mnesia:foldl(Contraint, [], employee) end, mnesia:transaction(Find).

Mnesia用户手册:五,Mnesia高级特性

本章描述了构建分布式、容错的Mnesia数据库相关的高级特性: 1)索引 2)分布和容错 3)表分片 4)本地内容表 5)无盘节点

6)更多的schema管理 7)Mnesia事件处理 8)Mnesia应用调试 9)Mnesia里的并发进程 10)原型

1,索引

如果我们知道record的key,那么数据获取和匹配在执行起来都很高效 相反如果不知道record的key,那么表里所有的record都必须搜索 当表越来越大时,表的搜索就越来越耗时 Mnesia的索引就是用来解决这个问题的 下面的两个方法对已有的表操作索引:

Java代码

? ?

mnesia:add_table_index(Tab, AttributeName) -> {aborted, R} | {atomic, ok} mnesia:del_table_index(Tab, AttributeName) -> {aborted, R} | {atomic, ok}

mnesia:add_table_index(Tab, AttributeName) -> {aborted, R} | {atomic, ok} mnesia:del_table_index(Tab, AttributeName) -> {aborted, R} | {atomic, ok}

这两个方法对AttributeName定义的域加索引和删除索引:

Java代码

? mnesia:add_table_index(employee, salary)

mnesia:add_table_index(employee, salary)

Mnesia的索引用于以下3个方法:

1)mnesia:index_read(Tab, SecondaryKey, AttributeName) -> transaction abort | RecordList

通过在索引里查询SecondaryKey来找到primary key,这样就能避免对整张表穷举搜索 2)mnesia:index_match_object(Pattern, AttributeName) -> transaction abort | RecordList

通过Pattern里的AttributeName域查找secondary key,然后找到primary key 3)mnesia:match_object(Pattern) -> transaction abort | RecordList 该方法可以使用任何索引

2,分布和容错

Mnesia是分布式、容错的DBMS,可以以多种方式在Erlang节点上备份表 Mnesia程序员不需要了解不同的表位于哪里,只用在程序里指定表的名字 这就是“位置透明”:

1)数据位于本地节点还是远程节点对程序员没有影响,只不过远程节点会慢些 2)数据库可以重新配置,表可以在节点之间移动,这些操作不影响用户程序 每张表有许多系统属性,如index和type

在表创建之时表属性就指定了,例如创建拥有两个RAM备份的新表:

Java代码

? ? ?

mnesia:create_table(foo, [{ramp_copies, [N1, N2]},

{attribtues, record_info(fields, foo)}]).

mnesia:create_table(foo, [{ramp_copies, [N1, N2]},

{attribtues, record_info(fields, foo)}]).

表可以有如下属性,每个属性使用一个Erlang节点list 1)ram_copies

表的RAM备份会存在于Erlang节点list中的每个节点上 对于RAM备份,写操作不会写到硬盘里 但是如果RAM备份需要持久化时可以这样做:

i)mnesia:dump_tables/1方法用来将RAM表备份导入到硬盘 ii)表副本可以备份 2)disc_copies

表会位于RAM中,而且表的副本会存在于Erlang节点list中的每个节点的硬盘上 对该表的写操作会同时写入到RAM和硬盘备份里 3)disc_only_copies

表的副本只会位于Erlang节点list中每个节点的硬盘上 这种类型的表副本的缺点是访问速度,优点主要是不占内存

简单的说,ram_copies表示本地节点和list中节点都会存RAM表 disc_copies则本地存RAM表,list中存硬盘表 disc_only_copies则只会list中存硬盘表

使用表副本有两个原因:容错和速度

值得注意的是,表备份对这两个系统需求都提供了解决方案 如果有两个表副本,则一旦一个表崩溃了,还有另一个可以工作

如果有两个节点上的表副本,则两个节点上的应用可以直接从本地读数据而不用访问网络

对于读频繁而写很少的分布式应用,表副本就会大大加速读的速度,因为直接在本地节点读取数据 而这样做的缺点写速度减慢了,因为执行一个写操作时要花更多代价来更新表副本

3,表分片

为了处理超大型的表,表分片的概念引入,基本原理是将表分成多个可以管理的片断

每个片断都实现为一等Mnesia表,它们可以像其他表一样备份,可以拥有索引等等,但是不能有local_content和snmp连接

为了从片断表里访问数据,Mnesia必须决定该record属于哪张表,这通过mnesia_frag模块来实现mnesia_access callback行为 (略)

4,本地内容表

所有节点上的表副本的内容一样,但是有时候不同节点的内容不同有优点

如果我们创建表时指定{local_content, true}属性,则写操作只在本地副本上执行 而且,当在启动时初始化表,则表只会在本地初始化而表内容不会复制到其他节点

5,无盘节点

可以在无盘的节点上运行Mnesia,当然在这些节点上不可能拥有disc_copies或disc_only_copies类型的备份

最麻烦的是schema表,因为Mnesia需要schema来初始化自己 schema表可以位于一个或多个节点上

schema表的存储类型可以为disc_copies或ram_copies(不能是disc_only_copies) Mnesia启动时使用schema表来决定应该和哪些节点建立联系

如果其他节点已经启动,则启动节点将其他节点的表定义和自己的表定义合并

参数extra_db_nodes包含一个节点list,Mnesia除了schema里的节点,还要和该参数的节点建立联系,默认值为[]

因此,当无盘节点需要从网络上的一个远程节点找到schema定义,则我们需要从-mnesia extra_db_nodes参数节点列表支持该信息

如果没有这个配置参数,Mnesia会以一个单节点系统启动

可以使用mnesia:change_config/2来给'extra_db_node'赋值并且强制建立一个连接,即mnesia:change_config(extra_db_nodes, NodeList) 应用参数schema_location控制Mnesia在哪里搜索schema: 1)disc

强制硬盘,schema假设位于Mnesia目录,如果找不到,则Mnesia拒绝启动 2)ram

强制ram,schema只位于ram中,启动时会生成一个很小的新schema 这个默认schema只包含schema表的定义并且只位于本地节点 3)opt_disc

可选的硬盘,schema可能只位于硬盘或ram

如果硬盘上找不到schema,Mnesia启动一个无盘节点(schema表的存储类型为ram_copies) 如果schema_location设置为opt_disc,则方法mnesia:change_table_copy_type/3可以用来改变schema的存储类型:

Java代码

? ? ?

1> mneisa:start(). ok

2> mnesia:change_table_copy_type(schema, node(), disc_copies).

?? {atomic, ok}

1> mneisa:start(). ok

2> mnesia:change_table_copy_type(schema, node(), disc_copies). {atomic, ok}

6,更多的Schema管理

可以从Mnesia添加和删除节点,这可以通过添加schema副本到这些节点来完成

mnesia:add_table_copy/3和mnesia:del_table_copy/2可以用来添加和删除schema表副本 添加一个节点会影响两点:1,允许其他表备份到该节点;2,它会在启动时连接硬盘节点 mnesia:del_table_copy(schema, mynode@host)从Mnesia系统删除'mynode@host'节点 mnesia:system_info(schema_location)和mnesia:system_info(extra_db_notes)用来决定schema_location和extra_db_nodes的值

mnesia:info/0用来打印出系统信息,可以在Mnesia启动之前就运行此方法

7,Mnesia事件处理

Mnesia可能生成系统事件和表事件这两种事件 用户进程可以订阅这些事件:

mneisa:subscribe(Event-Category)保证符合Event-Category类型的事件副本会发送给调用进程

mnesia:unsubscribe(Event-Category)对符合Event-Category类型的事件删除订阅 Event-Category可以为system或{table, Tab, simple}/{table, Tab, detailed}

系统事件语法为{mnesia_system_event, Event},表事件语法为{mnesia_table_event, Event}

所有的系统事件有Mnesia的gen_event handler来订阅,默认为mnesia_event

mnesia:system_info(subscribers)和mnesia:table_info(Tab, subscribers)用来决定哪个进程订阅了事件

系统事件

{mnesia_up, Node} {mnesia_down, Node}

{mnesia_checkpoint_activated, Checkpoint} {mnesia_checkpoint_deactivated, Checkpoint} {mnesia_overload, Details}

{inconsistent_database, Context, Node} {mnesia_fatal, Format, Args, BinaryCode} {mnesia_info, Format, Args} {mnesia_error, Format, Args} {mnesia_user, Event} 表事件

{write, NewRecord, ActivityId} {delete_object, OldRecord, ActivityId} {delete, {Tab, Key}, ActivityId}

{write, Table, NewRecord, [OldRecords], ActivityId} {delete, Table, What, [OldRecords], ActivityId}

9,Mnesia应用调试


Mnesia(8).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:基于单片机的数字电压表开题报告

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: