Wiki

Clone wiki

Erlang 语言学习笔记 / Mnesia_数据库

Mnesia 数据库

一个非常悲剧的遗留问题,dest 的容量被限制在了2G,使用 dest 的 Mnesia 单个表也被限制在了2G大小了。(注:部分文章说是4G,但是erlang文档上写着 dest 的大小限制为2G。)

Eshell V4.9 (abort with ^G)
1>
1> mnesia:create_schema([node()]).
ok
2> mnesia:start().
ok
3> mnesia:create_table(funky, []).
{atomic,ok}
4> mnesia:info().
---> Processes holding locks <---
---> Processes waiting for locks <---
---> Pending (remote) transactions <---
---> Active (local) transactions <---
---> Uncertain transactions <---
---> Active tables <---
funky : with 0 records occupying 269 words of mem
schema : with 2 records occupying 353 words of mem
===> System info in version "1.0", debug level = none <===
opt_disc. Directory "/tmp/funky" is used.
use fall-back at restart = false
running db nodes = [nonode@nohost]
stopped db nodes = []
remote = []
ram_copies = [funky]
disc_copies = [schema]
disc_only_copies = []
[{nonode@nohost,disc_copies}] = [schema]
[{nonode@nohost,ram_copies}] = [funky]
1 transactions committed, 0 aborted, 0 restarted, 1 logged to disc
0 held locks, 0 in queue; 0 local transactions, 0 remote
0 transactions waits for other nodes: []
ok

模式函数

· mnesia:create_schema(NodeList). 该函数用来初始化一个新的空模式,在Mnesia 启动之前这是一个强制性的必要步骤。Mnesia是一个真正分布式的数据库管理系统,而 模式是一个系统表,它被复制到Mnesia系统的所有节点上。如果NodeList中某一个节点 已经有模式,则该函数会失败。该函数需要NodeList中所有节点上的Mnesia都停止之后 才执行。应用程序只需调用该函数一次,因为通常只需要初始化数据库模式一次。

· mnesia:delete_schema(DiscNodeList). 该函数在DiscNodeList节点上删除旧的模 式,它也删除所有旧的表和数据。该函数需要在所有数据库节点(db_nodes)上的 Mnesia都停止后才能执行。

· mnesia:delete_table(Tab). 该函数永久删除表Tab的所有副本。

· mnesia:clear_table(Tab). 该函数永久删除表Tab的全部记录。

· mnesia:move_table_copy(Tab, From, To). 该函数将表Tab的拷贝从From节点移 动到To节点。表的存储类型{type}被保留,这样当移动一个RAM表到另一个节点时,在 新节点上也维持一个RAM表。在表移动的过程中仍然可以有事务执行读和写操作。

· mnesia:add_table_copy(Tab, Node, Type). 该函数在Node节点上创建Tab表的 备份。Type参数必须是ram_copies、 disc_copies或者是disc_only_copies。如果我们加一 19 个系统表schema的拷贝到某个节点上,这意味着我们要Mnesia模式也驻留在那里。这个 动作扩展了组成特定Mnesia系统节点的集合。

· mnesia:del_table_copy(Tab, Node). 该函数在Node节点上删除Tab表的备份,当 最后一个备份被删除后,表本身也被删除。

· mnesia:transform_table(Tab, Fun, NewAttributeList, NewRecordName).

该函数改变表Tab中所有记录的格式。它对表里所有记录调用参数Fun指明的函数进行处 理,从表中取得旧的记录类型处理后返回新的纪录类型,表的键(key)可以不被改变。 -record(old, {key, val}). -record(new, {key, val, extra}). Transformer = fun(X) when record(X, old) ->

  1. new{key = X#old.key, val = X#old.val, extra = 42} end, {atomic, ok} = mnesia:transform_table(foo, Transformer, record_info(fields, new), new), Fun的参数也可以是原子ignore,它表示只更新表的元(meta)数据,不推荐使用(因为 它将在元数据和实际数据之间产生矛盾)。但有可能用户需要用其在离线时做自己的转换。

· change_table_copy_type(Tab, Node, ToType). 该函数改变表的存储类型。例如, 将在Node节点上指定的内存类型的表Tab改为磁盘类型的表.

建立数据库的步骤

用一个已知的实例,我们说明怎样在被称为a@gin和b@skeppet这样两个分开的节点上运行在第2 章描述的公司数据库。要想在这两个节点上运行公司数据库,每个节点在Mnesia启动前必须有 一个在初始化模式时建立的Mnesia目录。 有两种方式指定Mnesia目录: 启动Erlang shell的时候或在应用程序脚本中通过一个应用程序参数来指定Mnesia目录。先前已 用过下面的实例为我们的公司数据库创建目录: %erl -mnesia dir '"/ldisc/scratch/Mnesia.Company"' 如果没有输入命令行旗标(flag),则Mnesia使用当前节点Erlang shell启动时的工作目录作为 Mnesia目录。 启动我们的公司数据库并使得其运行在两个分开的节点上,我们键入下列命令: 1. 在节点gin上调用: gin %erl -sname a -mnesia dir '"/ldisc/scratch/Mnesia.company"' 2. 在节点skeppet上调用: skeppet %erl -sname b -mnesia dir '"/ldisc/scratch/Mnesia.company"' 3. 在这两个节点之一上: (a@gin1)>mnesia:create_schema([a@gin, b@skeppet]). 4. 在两个节点上调用函数mnesia:start()。 5. 在两个节点之一执行以下代码来初始化数据库: dist_init() -> mnesia:create_table(employee, [{ram_copies, [a@gin, b@skeppet]}, {attributes, record_info(fields, employee)}]), mnesia:create_table(dept, [{ram_copies, [a@gin, b@skeppet]}, {attributes, record_info(fields, dept)}]), mnesia:create_table(project, [{ram_copies, [a@gin, b@skeppet]}, {attributes, record_info(fields, project)}]), mnesia:create_table(manager, [{type, bag}, {ram_copies, [a@gin, b@skeppet]}, {attributes, record_info(fields, manager)}]), 21 mnesia:create_table(at_dep, [{ram_copies, [a@gin, b@skeppet]}, {attributes, record_info(fields, at_dep)}]), mnesia:create_table(in_proj, [{type, bag}, {ram_copies, [a@gin, b@skeppet]}, {attributes, record_info(fields, in_proj)}]). 如上所示,两个目录驻留在不同的节点上。因为/ldisc/scratch (本地磁盘)存在于这两个不同的节点 上。 通过执行这些命令,我们已经配置了两个Erlang节点并初始化以运行公司数据库。这些操作仅需 要在设置时做一次,以后这两个节点上的系统将通过调用mnesia:start()来启动系统。

Updated