查看源代码 mnesia (mnesia v4.23.3)

一个分布式的键值数据库管理系统

以下是 Mnesia 提供的一些最重要和最具吸引力的功能:

  • 适用于电信应用的关系/对象混合数据模型。
  • 一个数据库管理系统查询语言,查询列表推导(QLC)作为一个附加库。
  • 持久性。表可以一致地保存在磁盘和主内存中。
  • 复制。表可以在多个节点上复制。
  • 原子事务。一系列表操作可以组合成一个原子事务。
  • 位置透明。程序可以编写,而无需知道实际的数据位置。
  • 极快的实时数据搜索。
  • 模式操作例程。数据库管理系统可以在运行时重新配置,而无需停止系统。

本参考手册描述了 Mnesia API。这包括定义和操作 Mnesia 表的函数。

本参考手册中的所有函数都可以与使用列表推导符号的查询以任何组合方式使用。有关查询符号的信息,请参阅 STDLIB 中的 qlc 手册页。

Mnesia 中的数据组织为一组表。每个表都有一个必须是原子(atom)的名称。每个表由 Erlang 记录组成。用户负责记录定义。每个表也有一组属性。以下是与每个表关联的一些属性:

  • type。每个表可以具有 setordered_setbag 语义。请注意,目前 ordered_set 不支持 disc_only_copies

    如果表的类型为 set,则每个键指向一个或零个记录。

    如果插入的新项与现有记录的键相同,则旧记录将被覆盖。但是,如果表的类型为 bag,则每个键可以映射到多个记录。类型为 bag 的表中的所有记录都是唯一的,只有键可以重复。

  • record_name。存储在表中的所有记录必须具有相同的名称。这些记录必须是相同记录类型的实例。

  • ram_copies。表可以在多个 Erlang 节点上复制。ram_copies 属性指定保存 RAM 副本的 Erlang 节点列表。这些副本可以定期转储到磁盘。但是,这些副本的更新不会在事务基础上写入磁盘。

  • disc_copies。此属性指定表在 RAM 和磁盘中保留的 Erlang 节点列表。对表的所有更新都在实际表中执行,并且还记录到磁盘。如果某个节点上的表的类型为 disc_copies,则整个表驻留在 RAM 内存和磁盘中。对表执行的每个事务都会追加到一个 LOG 文件并写入 RAM 表中。

  • disc_only_copies。一些或所有表副本可以仅保存在磁盘上。这些副本比基于 RAM 的副本慢得多。

  • index。这是一个属性名称或整数列表,指定 Mnesia 要在其上构建和维护额外索引表的元组位置。

  • local_content。当应用程序需要内容对每个节点都是本地的表时,可以使用 local_content 表。表名称为所有 Mnesia 节点所知,但其内容在每个节点上都是唯一的。这意味着必须在本地完成对此类表的访问。将字段 local_content 设置为 true 以启用 local_content 行为。默认值为 false

  • majority。此属性为 truefalse;默认值为 false。当为 true 时,必须有大多数表副本可用,更新才能成功。多数检查可以在具有任务关键数据的表上启用,在这些表中,避免因网络分裂而导致的不一致至关重要。

  • snmp。每个(基于集合的)Mnesia 表也可以自动转换为简单网络管理协议(SNMP)有序表。此属性指定 SNMP 键的类型。

  • attributes。插入到表中的记录的属性名称。

有关表属性的完整集合及其详细信息,请参阅 mnesia:create_table/2

本参考手册使用人员表来说明各种示例。假设有以下记录定义:

-record(person, {name,
                 age = 0,
                 address = unknown,
                 salary = 0,
                 children = []}),

第一个记录属性是主键,或简称键。

函数描述按字母顺序排序。建议首先阅读 mnesia:create_table/2mnesia:lock/2mnesia:activity/4,然后再继续学习其余部分。

在事务上下文中写入或删除会在事务期间创建每个修改记录的本地副本。在迭代期间,即 mnesia:foldl/4mnesia:foldr/4mnesia:next/2mnesia:prev/2mnesia:snmp_get_next_index/2,Mnesia 会补偿每个写入或删除的记录,这可能会降低性能。

如果可能,请避免在迭代表之前在同一事务中写入或删除记录。

配置参数

Mnesia 读取以下应用程序配置参数:

  • -mnesia access_module Module。Mnesia 活动访问回调模块的名称。默认值为 mnesia

  • -mnesia auto_repair true | false。此标志控制 Mnesia 是否自动尝试修复未正确关闭的文件。默认值为 true

  • -mnesia backup_module Module。Mnesia 备份回调模块的名称。默认值为 mnesia_backup

  • -mnesia debug Level。控制 Mnesia 的调试级别。可能的值如下:

    • none - 没有跟踪输出。这是默认值。

    • verbose - 激活重要调试事件的跟踪。这些事件生成 {mnesia_info, Format, Args} 系统事件。进程可以使用 mnesia:subscribe/1 订阅这些事件。这些事件始终发送到 Mnesia 事件处理程序。

    • debug - 激活 verbose 级别上的所有事件,以及所有调试事件的完整跟踪。这些调试事件生成 {mnesia_info, Format, Args} 系统事件。进程可以使用 mnesia:subscribe/1 订阅这些事件。这些事件始终发送到 Mnesia 事件处理程序。在此调试级别,Mnesia 事件处理程序开始订阅模式表中的更新。

    • trace - 激活 debug 级别上的所有事件。在此级别,Mnesia 事件处理程序开始订阅所有 Mnesia 表中的更新。此级别仅适用于调试小型玩具系统,因为可能会生成许多大型事件。

    • false - none 的别名。

    • true - debug 的别名。

  • -mnesia core_dir Directory。存储 Mnesia 核心文件的目录名称,或 false。设置它意味着如果发生崩溃,仅 RAM 的节点也会生成核心文件。

  • -mnesia dc_dump_limit Number。控制从内存转储 disc_copies 表的频率。当 filesize(Log) > (filesize(Tab)/Dc_dump_limit) 时,将转储表。较低的值会减少 CPU 开销,但会增加磁盘空间和启动时间。默认值为 4。

  • -mnesia dir Directory。存储所有 Mnesia 数据的目录名称。目录名称对于当前节点必须是唯一的。两个节点绝不能共享同一个 Mnesia 目录。结果是不可预测的。

  • -mnesia dump_disc_copies_at_startup true | false。如果设置为 false,则在加载表期间,禁用在启动期间转储 disc_copies 表。默认值为 true。

  • -mnesia dump_log_load_regulation true | false。控制日志转储是尽可能快地执行,还是转储器执行自己的负载调节。默认值为 false

    此功能是临时的,将在未来的版本中删除

  • -mnesia dump_log_update_in_place true | false。控制日志转储是在原始数据文件的副本上执行,还是在原始数据文件上执行。默认值为 true

  • -mnesia dump_log_write_threshold MaxMax 是一个整数,指定在执行新的日志转储之前,允许写入事务日志的最大次数。默认值为 1000 次日志写入。

  • -mnesia dump_log_time_threshold MaxMax 是一个整数,指定以毫秒为单位的转储日志间隔。默认值为 3 分钟。如果在 dump_log_time_threshold 毫秒内未执行转储,则无论执行的写入次数如何,都会执行新的转储。

  • -mnesia event_module Module。 Mnesia 事件处理回调模块的名称。默认为 mnesia_event

  • -mnesia extra_db_nodes Nodes 指定一个节点列表,除了在模式中找到的节点之外,Mnesia 还会与之建立联系。默认为 [](空列表)。

  • -mnesia fallback_error_function {UserModule, UserFunc}。指定一个用户提供的回调函数,如果在安装了回退并且 Mnesia 在另一个节点上崩溃时调用该函数。Mnesia 使用一个参数调用该函数,即正在崩溃的节点的名称,例如 UserModule:UserFunc(DyingNode)。必须重新启动 Mnesia,否则数据库可能会不一致。默认行为是终止 Mnesia。

  • -mnesia max_wait_for_decision Timeout。指定 Mnesia 等待其他节点共享有关不明确事务结果的知识的时间。默认情况下,Timeout 设置为原子 infinity。这意味着如果 Mnesia 在启动时检测到结果不明确的“重量级事务”,则本地 Mnesia 会一直等待,直到在中断事务中涉及的其他一些(在最坏的情况下是所有)节点上启动 Mnesia。这是一种罕见的情况,但如果发生,Mnesia 不会猜测其他节点上的事务是已提交还是已终止。Mnesia 会一直等待,直到它知道结果,然后采取相应的行动。

    如果 Timeout 设置为毫秒的整数值,Mnesia 会强制“重量级事务”完成,即使目前事务的结果不明确。在 Timeout 毫秒后,Mnesia 会提交或终止事务并继续启动。这可能导致事务在某些节点上提交而在其他节点上终止的情况。如果事务是模式事务,则不一致可能是致命的。

  • -mnesia no_table_loaders NUMBER。指定启动期间并行表加载器的数量。如果网络延迟较高或者许多表包含少量记录,则使用更多加载器会更好。默认为 2

  • -mnesia send_compressed Level。指定在将表从本地节点复制到另一个节点时使用的压缩级别。默认为 0

    Level 必须是区间 [0, 9] 中的整数,其中 0 表示不压缩,9 表示最大压缩。在将其设置为非零值之前,请确保远程节点理解此配置。

  • -mnesia max_transfer_size Number。指定将表从本地节点复制到另一个节点时要使用的单个数据包的估计大小(以字节为单位)。默认为 64000

  • -mnesia schema_location Loc。控制 Mnesia 在哪里查找其模式。参数 Loc 可以是以下原子之一

    • disc - 强制磁盘。假定模式位于 Mnesia 目录中。如果找不到模式,Mnesia 会拒绝启动。这是旧的行为。

    • ram - 强制 RAM。模式仅驻留在 RAM 中。在启动时,会生成一个新的微型模式。此默认模式仅包含模式表的定义,并且仅驻留在本地节点上。由于在默认模式中未找到其他节点,因此必须使用配置参数 extra_db_nodes,以使节点与其他节点共享其表定义。

      参数 extra_db_nodes 也可以在基于磁盘的节点上使用。

    • opt_disc - 可选磁盘。模式可以驻留在磁盘上或 RAM 中。如果在磁盘上找到模式,Mnesia 将作为基于磁盘的节点启动,并且模式表的存储类型为 disc_copies。如果在磁盘上找不到模式,Mnesia 将作为无磁盘节点启动,并且模式表的存储类型为 ram_copies。应用程序参数的默认值为 opt_disc

首先,检查 SASL 应用程序参数,然后检查命令行标志,最后选择默认值。

另请参阅

application, dets, disk_log, ets, qlc

摘要

函数

终止当前事务。

激活检查点。

AccessContext 中执行 Fun

AccessContext 中执行 Fun

将表复制到远程节点。

添加表索引。

返回表中的所有键。

在不受事务保护的上下文中调用 Fun

等效于 backup/2

备份数据库中的所有表。

备份检查点中的所有表。

更改配置设置。

更改表访问模式。

更改表的存储类型。

重新配置表片段属性。

更改表加载顺序。

更改表多数。

删除表 Tab 中的所有条目。

在指定节点上创建新模式。

停用检查点。

删除表的副本。

删除表索引。

删除表 Tab 中具有键 Key 的所有记录。

删除给定节点上的模式。

永久删除表 Tab 的所有副本。

mnesia:all_keys/1 等效的脏读取操作。

mnesia:delete/3 等效的脏读取操作。

返回表中第一条记录的键。

mnesia:index_read/3 等效的脏读取操作。

返回表中最后一条记录的键。

返回表中的下一个键。

返回表中的上一个键。

mnesia:read/3 等效的脏读取操作。

mnesia:select/2 等效的脏读取操作。

对计数器记录进行脏更新。

mnesia:write/3 等效的脏读取操作。

执行用户发起的本地日志文件转储。

将 ram_copies 表转储到磁盘。

将本地表转储到文本文件中。

返回描述特定 Mnesia 错误的字符串。

等效于 ets(Fun, [])

在不受事务保护的原始上下文中调用 Fun

返回表中第一条记录的键。

Table 中的每条记录调用 Fun

Table 中的每条记录调用 Fun

强制将表加载到系统中。

匹配记录并使用索引信息。

匹配记录并使用索引信息。

通过索引表读取记录。

在终端上打印系统信息。

安装一个备份作为回退。

如果在事务上下文中则返回 true。

返回表中最后一条记录的键。

从文本文件加载表。

显式获取锁。

为记录匹配 Pattern

移动表副本。

返回表中的下一个键。

返回表中的上一个键。

读取具有给定键的记录。

向 Mnesia 事件处理程序报告用户事件。

恢复备份。

调用函数 mnesia:delete(Tab, Key, sticky_write)

在终端上打印有关所有表定义的信息。

在终端上打印有关一个表定义的信息。

继续选择对象。

根据 MatchSpec 选择 Tab 中的对象。

根据 MatchSpec 选择 Tab 中的对象。

更改 Mnesia 的内部调试级别。

设置所有表的主节点。

设置一个表的主节点。

移除 SNMP 操作表的可能性。

从 SNMP 索引获取相应的 Mnesia 键。

获取下一个按字典顺序排列的行的索引。

检索由 SNMP 索引索引的行。

将 Mnesia 表组织为 SNMP 表。

启动本地 Mnesia 系统。

在当前节点本地停止 Mnesia。

订阅 EventCategory 类型的事件。

在不受事务保护的上下文中调用 Fun

对本地日志文件执行文件同步。

同步执行事务。

返回有关 Mnesia 系统的信息。

等效于 table/2

返回 QLC 查询句柄。

返回关于表的本地信息。

将带有参数 ArgsFun 作为事务执行。

更改表中所有记录的格式。

卸载回退。

停止向调用者发送 EventCategory 类型的事件。

等待表可访问。

将记录写入数据库。

Record 写入表 Tab

类型

-type activity() ::
          ets | async_dirty | sync_dirty | transaction | sync_transaction |
          {transaction, Retries :: non_neg_integer()} |
          {sync_transaction, Retries :: non_neg_integer()}.
链接到此类型

config_key()

查看源代码 (未导出)
-type config_key() :: extra_db_nodes | dc_dump_limit.
链接到此类型

config_result()

查看源代码 (未导出)
-type config_result() :: {ok, config_value()} | {error, term()}.
链接到此类型

config_value()

查看源代码 (未导出)
-type config_value() :: [node()] | number().
链接到此类型

create_option()

查看源代码 (未导出)
-type create_option() ::
          {access_mode, read_write | read_only} |
          {attributes, [atom()]} |
          {disc_copies, [node()]} |
          {disc_only_copies, [node()]} |
          {index, [index_attr()]} |
          {load_order, non_neg_integer()} |
          {majority, boolean()} |
          {ram_copies, [node()]} |
          {record_name, atom()} |
          {snmp, SnmpStruct :: term()} |
          {storage_properties, [{Backend :: module(), [BackendProp :: _]}]} |
          {type, set | ordered_set | bag} |
          {local_content, boolean()} |
          {user_properties, proplists:proplist()}.
链接到此类型

debug_level()

查看源代码 (未导出)
-type debug_level() :: none | verbose | debug | trace.
链接到此类型

index_attr()

查看源代码 (未导出)
-type index_attr() :: atom() | non_neg_integer() | {atom()}.
-type lock_kind() :: write_locks() | read_locks().
链接到此类型

read_locks()

查看源代码 (未导出)
-type read_locks() :: read.
-type result() :: ok | {error, Reason :: term()}.
链接到此类型

select_continuation()

查看源代码 (未导出)
-type select_continuation() :: term().
链接到此类型

snmp_struct()

查看源代码 (未导出)
-type snmp_struct() :: [{atom(), snmp_type() | tuple_of(snmp_type())}].
-type snmp_type() :: fix_string | string | integer.
链接到此类型

storage_type()

查看源代码 (未导出)
-type storage_type() :: ram_copies | disc_copies | disc_only_copies.
链接到此类型

t_result(Res)

查看源代码 (未导出)
-type t_result(Res) :: {atomic, Res} | {aborted, Reason :: term()}.
-type table() :: atom().
-type tuple_of(_T) :: tuple().
链接到此类型

write_locks()

查看源代码 (未导出)
-type write_locks() :: write | sticky_write.

函数

-spec abort(Reason :: term()) -> no_return().

终止当前事务。

使事务静默返回元组 {aborted, Reason}。终止 Mnesia 事务意味着将异常抛出到封闭的 catch。因此,表达式 catch mnesia:abort(x) 不会终止事务。

链接到此函数

activate_checkpoint(Args)

查看源代码
-spec activate_checkpoint([Arg]) -> {ok, Name, [node()]} | {error, Reason :: term()}
                             when
                                 Arg ::
                                     {name, Name} |
                                     {max, [table()]} |
                                     {min, [table()]} |
                                     {allow_remote, boolean()} |
                                     {ram_overrides_dump, boolean()}.

激活检查点。

检查点是系统的一致视图。可以在一组表上激活检查点。然后可以遍历此检查点,并显示系统在激活检查点时存在的视图,即使正在或已经操作表。

Args 是以下元组的列表

  • {name,Name}Name 是检查点名称。每个检查点必须具有对于关联节点唯一的名称。只有在检查点停用后才能重复使用该名称。默认情况下,会生成一个可能唯一的名称。
  • {max,MaxTabs}MaxTabs 是要包含在检查点中的表列表。默认为 []。对于这些表,冗余最大化,并且检查点信息与所有副本一起保留。如果表有多个副本,则检查点的容错能力更强。当通过模式操作函数 mnesia:add_table_copy/3 添加新副本时,也会自动附加一个保留器。
  • {min, MinTabs}MinTabs 是一个需要包含在检查点中的表列表。默认值是 []。对于这些表,冗余度被最小化,检查点信息仅保留在一份副本中,最好是在本地节点上。
  • {allow_remote, Bool}false 表示所有的保留者必须是本地的。如果表没有驻留在本地,则无法激活检查点。true 允许在任何节点上分配保留者。默认值是 true
  • {ram_overrides_dump, Bool}。仅适用于 ram_copiesBool 允许您选择备份表在 RAM 中的状态,还是在磁盘上的状态。true 表示 RAM 中最新的已提交记录将被包含在检查点中。这些是应用程序访问的记录。false 表示转储到 DAT 文件中的记录将被包含在检查点中。这些记录在启动时加载。默认值是 false

返回 {ok, Name, Nodes}{error, Reason}Name 是(可能生成的)检查点名称。Nodes 是参与检查点的节点。只有保留检查点保留器的节点才知道检查点。

链接到此函数

activity(AccessContext, Fun)

查看源代码
-spec activity(AccessContext, Fun) -> t_result(Res) | Res
                  when AccessContext :: activity(), Fun :: fun(() -> Res).

AccessContext 中执行 Fun

调用 mnesia:activity(AccessContext, Fun, Args, AccessMod),其中 AccessMod 是通过 mnesia:system_info(access_module) 获取的默认访问回调模块。Args 默认为 [](空列表)。

链接到此函数

activity(Kind, Fun, Args, Mod)

查看源代码
-spec activity(AccessContext, Fun, [Arg :: _], Mod) -> t_result(Res) | Res
                  when AccessContext :: activity(), Fun :: fun((...) -> Res), Mod :: atom().

AccessContext 中执行 Fun

使用参数 Args 执行函数对象 Fun

在活动中执行的代码可以包含一系列表操作函数,这些函数在 AccessContext 中执行。目前,支持以下访问上下文:

  • transaction - {transaction, infinity} 的简写形式。

  • {transaction, Retries} - 调用 mnesia:transaction(Fun, Args, Retries)。请注意,如果事务成功(原子性),则返回 Fun 的结果,否则该函数将以中止原因退出。

  • sync_transaction - {sync_transaction, infinity} 的简写形式。

  • {sync_transaction, Retries} - 调用 mnesia:sync_transaction(Fun, Args, Retries)。请注意,如果事务成功(原子性),则返回 Fun 的结果,否则该函数将以中止原因退出。

  • async_dirty - 调用 mnesia:async_dirty(Fun, Args)

  • sync_dirty - 调用 mnesia:sync_dirty(Fun, Args)

  • ets - 调用 mnesia:ets(Fun, Args)

此函数 (mnesia:activity/4) 与函数 mnesia:transaction/3mnesia:sync_transaction/3mnesia:async_dirty/2mnesia:sync_dirty/2mnesia:ets/2 的重要区别在于,参数 AccessMod 是一个回调模块的名称,该模块实现了 mnesia_access 行为。

Mnesia 将调用转发到以下函数:

  • mnesia:lock/2 (read_lock_table/1, write_lock_table/1)
  • mnesia:write/3 (write/1, s_write/1)
  • mnesia:delete/3 (delete/1, s_delete/1)
  • mnesia:delete_object/3 (delete_object/1, s_delete_object/1)
  • mnesia:read/3 (read/1, wread/1)
  • mnesia:match_object/3 (match_object/1)
  • mnesia:all_keys/1
  • mnesia:first/1
  • mnesia:last/1
  • mnesia:prev/2
  • mnesia:next/2
  • mnesia:index_match_object/4 (index_match_object/2)
  • mnesia:index_read/3
  • mnesia:table_info/2

到对应的:

  • AccessMod:lock(ActivityId, Opaque, LockItem, LockKind)
  • AccessMod:write(ActivityId, Opaque, Tab, Rec, LockKind)
  • AccessMod:delete(ActivityId, Opaque, Tab, Key, LockKind)
  • AccessMod:delete_object(ActivityId, Opaque, Tab, RecXS, LockKind)
  • AccessMod:read(ActivityId, Opaque, Tab, Key, LockKind)
  • AccessMod:match_object(ActivityId, Opaque, Tab, Pattern, LockKind)
  • AccessMod:all_keys(ActivityId, Opaque, Tab, LockKind)
  • AccessMod:first(ActivityId, Opaque, Tab)
  • AccessMod:last(ActivityId, Opaque, Tab)
  • AccessMod:prev(ActivityId, Opaque, Tab, Key)
  • AccessMod:next(ActivityId, Opaque, Tab, Key)
  • AccessMod:index_match_object(ActivityId, Opaque, Tab, Pattern, Attr, LockKind)
  • AccessMod:index_read(ActivityId, Opaque, Tab, SecondaryKey, Attr, LockKind)
  • AccessMod:table_info(ActivityId, Opaque, Tab, InfoItem)

ActivityId 是一个记录,表示包含 Mnesia 活动的标识。第一个字段(通过 element(1, ActivityId) 获取)包含一个原子,可以解释为活动类型:etsasync_dirtysync_dirtytidtid 表示该活动是一个事务。标识记录的其余结构的内部结构对于 Mnesia 来说是内部的。

Opaque 是 Mnesia 内部的不透明数据结构。

链接到此函数

add_table_copy(Tab, N, ST)

查看源代码
-spec add_table_copy(Tab, N, ST) -> t_result(ok) when Tab :: table(), N :: node(), ST :: storage_type().

将表复制到远程节点。

在节点 Node 上创建表的另一个副本。参数 Type 必须是原子 ram_copiesdisc_copiesdisc_only_copies 中的一个。例如,以下调用可确保在节点 Node 上也存在 person 表的磁盘副本。

mnesia:add_table_copy(person, Node, disc_copies)

此函数还可用于添加名为 schema 的表的副本。

链接到此函数

add_table_index(Tab, I)

查看源代码
-spec add_table_index(Tab, I) -> t_result(ok) when Tab :: table(), I :: index_attr().

添加表索引。

只要用户希望频繁使用除键字段之外的其他字段来查找记录,就可以使用表索引。如果此其他字段具有关联的索引,则这些查找可以在恒定的时间和空间内发生。例如,如果您的应用程序希望使用 age 字段来高效地查找具有特定年龄的所有人员,那么在 age 字段上建立索引可能是一个好主意。这可以通过以下调用来完成:

mnesia:add_table_index(person, age)

索引不是免费的。它们占用的空间与表大小成正比,并且导致插入表的操作执行速度稍慢。

-spec all_keys(Tab :: table()) -> [Key :: term()].

返回表中的所有键。

返回名为 Tab 的表中所有键的列表。此函数的语义与上下文相关。有关更多信息,请参阅 mnesia:activity/4。在事务上下文中,它会获取整个表的读取锁。

-spec async_dirty(Fun) -> Res | no_return() when Fun :: fun(() -> Res).

等效于 async_dirty(Fun, [])

链接到此函数

async_dirty(Fun, Args)

查看源代码
-spec async_dirty(Fun, [Arg :: _]) -> Res | no_return() when Fun :: fun((...) -> Res).

在不受事务保护的上下文中调用 Fun

Fun 中执行的 Mnesia 函数调用被映射到对应的脏函数。这仍然涉及日志记录、复制和订阅,但不涉及锁定、本地事务存储或提交协议。检查点保留器和索引被更新,但它们是脏更新的。与正常的 mnesia:dirty_* 操作一样,这些操作是半异步执行的。有关详细信息,请参阅 mnesia:activity/4 和《用户指南》。

可以在不使用事务的情况下操作 Mnesia 表。这有一些严重的缺点,但速度要快得多,因为不涉及事务管理器并且不设置锁。但是,脏操作确实保证了一定程度的一致性,并且脏操作不会返回损坏的记录。所有脏操作都为程序员提供了位置透明性,并且程序无需知道某个表的所在位置即可正常运行。

请注意,脏读取记录比在事务中读取记录效率高十倍以上。

根据应用程序的不同,对于某些操作使用脏函数可能是一个好主意。几乎所有可以在事务中调用的 Mnesia 函数都有一个效率更高的脏等效函数。

但是,请注意,如果使用脏操作来更新数据库,则存在数据库可能处于不一致状态的风险。只有在绝对必要时才出于性能原因使用脏操作。

请注意,在事务上下文中调用(嵌套)mnesia:[a]sync_dirty 会继承事务语义。

-spec backup(Dest :: term()) -> result().

等效于 backup/2

-spec backup(Dest :: term(), Mod :: module()) -> result().

备份数据库中的所有表。

激活一个涵盖所有 Mnesia 表(包括模式)的新检查点,该检查点具有最大冗余度,并使用 backup_checkpoint/2/3 执行备份。备份回调模块 BackupMod 的默认值是通过 mnesia:system_info(backup_module) 获取的。

链接到此函数

backup_checkpoint(Name, Dest)

查看源代码
-spec backup_checkpoint(Name, Dest) -> result() when Name :: term(), Dest :: term().

等效于 backup_checkpoint/3

链接到此函数

backup_checkpoint(Name, Dest, Mod)

查看源代码
-spec backup_checkpoint(Name, Dest, Mod) -> result()
                           when Name :: term(), Dest :: term(), Mod :: module().

备份检查点中的所有表。

使用备份模块 BackupMod 将表备份到外部介质。具有本地内容属性的表会按照它们在当前节点上的状态进行备份。BackupMod 是通过 mnesia:system_info(backup_module) 获取的默认备份回调模块。有关确切的回调接口(mnesia_backup behavior),请参阅《用户指南》。

链接到此函数

change_config(Config, Value)

查看源代码
-spec change_config(Config, Value) -> config_result()
                       when Config :: config_key(), Value :: config_value().

更改配置设置。

Config 应为以下配置参数的原子:

  • extra_db_nodes - Value 是 Mnesia 要尝试连接的节点列表。ReturnValueValue 中 Mnesia 已连接的节点。

    请注意,此函数只能用于连接到具有空模式的新启动的 RAM 节点(N.D.R.S.N.)。例如,如果在网络分区后使用此函数,则可能导致表不一致。

    请注意,Mnesia 可以连接到 ReturnValue 中返回的节点之外的其他节点。

  • dc_dump_limit - Value 是一个数字。请参阅 配置参数部分 中的描述。ReturnValue 是新值。请注意,此配置参数不是持久的。当 Mnesia 停止时,它将丢失。

链接到此函数

change_table_access_mode(Tab, Mode)

查看源代码
-spec change_table_access_mode(Tab :: table(), Mode) -> t_result(ok) when Mode :: read_only | read_write.

更改表访问模式。

AcccessMode 默认为原子 read_write,但也可以设置为原子 read_only。如果 AccessMode 设置为 read_only,则无法执行对表的更新。在启动时,无论何时以及 Mnesia 是否在其他节点上终止,Mnesia 始终会在本地加载 read_only 表。

链接到此函数

change_table_copy_type(Tab, Node, To)

查看源代码
-spec change_table_copy_type(Tab :: table(), Node :: node(), To :: storage_type()) -> t_result(ok).

更改表的存储类型。

例如:

mnesia:change_table_copy_type(person, node(), disc_copies)

person 表从 RAM 表转换为 Node 上的基于磁盘的表。

此函数还可用于更改名为 schema 的表的存储类型。模式表只能将 ram_copiesdisc_copies 作为存储类型。如果模式的存储类型是 ram_copies,则该节点上不能存在其他驻留在磁盘上的表。

链接到此函数

change_table_frag(Tab, FragProp)

查看源代码
-spec change_table_frag(Tab :: table(), FragProp :: term()) -> t_result(ok).

重新配置表片段属性。

参数 FragProp 应具有以下值之一:

  • {activate, FragProps} - 激活现有表的分片属性。FragProps 要么包含 {node_pool, Nodes},要么为空。

  • deactivate - 禁用表的分片属性。分片数必须为 1。没有其他表可以在其外键中引用此表。

  • {add_frag, NodesOrDist} - 向分片表添加分片。一个旧分片中的所有记录都被重新散列,并且大约一半的记录被移动到新的(最后一个)分片。所有在外键中引用此表的其他分片表都会自动获取新的分片。此外,它们的记录会以与主表相同的方式动态重新散列。

    参数 NodesOrDist 可以是节点列表,也可以是函数 mnesia:table_info(Tab, frag_dist) 的结果。假设参数 NodesOrDist 是一个排序列表,列表中最适合托管新副本的节点排在最前面。新片段的副本数量与第一个片段相同(参见 n_ram_copiesn_disc_copiesn_disc_only_copies)。 NodesOrDist 列表必须至少包含一个元素,对应每个需要分配的副本。

  • del_frag - 从分片表中删除一个片段。最后一个片段中的所有记录都会移动到其他片段之一。所有在其外键中引用此表的其他分片表也会自动丢失其最后一个片段。此外,它们的记录会以与主表相同的方式动态地重新哈希。

  • {add_node, Node} - 将一个节点添加到 node_pool。新的节点池会影响函数 mnesia:table_info(Tab, frag_dist) 返回的列表。

  • {del_node, Node} - 从 node_pool 中删除一个节点。新的节点池会影响函数 mnesia:table_info(Tab, frag_dist) 返回的列表。

链接到此函数

change_table_load_order(Tab, Order)

查看源代码
-spec change_table_load_order(Tab :: table(), Order) -> t_result(ok) when Order :: non_neg_integer().

更改表加载顺序。

默认情况下,LoadOrder 优先级为 0(零),但可以设置为任何整数。启动时,具有最高 LoadOrder 优先级的表会首先加载。

链接到此函数

change_table_majority(Tab, M)

查看源代码 (自 OTP R14B03 起)
-spec change_table_majority(Tab :: table(), M :: boolean()) -> t_result(ok).

更改表多数。

Majority 必须是布尔值。默认值为 false。当 true 时,必须有大多数表副本可用,更新才能成功。当在分片表上使用时,Tab 必须是基表名称。不允许直接更改单个片段上的 majority 设置。

-spec clear_table(Tab :: table()) -> t_result(ok).

删除表 Tab 中的所有条目。

-spec create_schema(Ns :: [node()]) -> result().

在指定节点上创建新模式。

在磁盘上创建一个新的数据库。会在每个节点的本地 Mnesia 目录中创建各种文件。请注意,每个节点的目录必须是唯一的。两个节点绝不能共享同一目录。如果可能,请使用本地磁盘设备来提高性能。

如果作为 DiscNodes 给出的任何 Erlang 节点未启动,如果 Mnesia 在任何节点上正在运行,或者如果任何节点已经有 schema,则 mnesia:create_schema/1 会失败。 使用 mnesia:delete_schema/1 来清除旧的错误 schema。

请注意,只有具有磁盘的节点才包含在 DiscNodes 中。无磁盘节点,即所有表(包括 schema)仅驻留在 RAM 中的节点,不得包含在内。

链接到此函数

create_table(Name, Opts)

查看源代码
-spec create_table(Name :: table(), Opts :: [create_option()]) -> t_result(ok).

创建表。

根据参数 TabDef 创建一个名为 Name 的 Mnesia 表。此列表必须是 {Item, Value} 元组的列表,其中允许以下值:

  • {access_mode, Atom}。访问模式默认为原子 read_write,但也可以设置为原子 read_only。如果 AccessMode 设置为 read_only,则无法对表执行更新。

    启动时,无论 Mnesia 何时以及是否在其他节点上终止,Mnesia 始终在本地加载 read_only 表。此参数返回表的访问模式。访问模式可以是 read_onlyread_write

  • {attributes, AtomList} 是记录的属性名称列表,这些记录将填充该表。默认值为 [key, val]。除了键之外,该表必须至少有一个额外的属性。

    在访问记录中的单个属性时,没有必要,甚至不建议将任何属性名称硬编码为原子。请改用构造 record_info(fields, RecordName)。它可以用于类型为 RecordName 的记录。

  • {disc_copies, Nodelist},其中 Nodelist 是此表应具有磁盘副本的节点列表。如果表副本的类型为 disc_copies,则对此表的特定副本的所有写入操作都会写入磁盘以及表的 RAM 副本。

    可以在一个节点上具有类型为 disc_copies 的复制表,在另一个节点上具有另一种类型。默认值为 []

  • {disc_only_copies, Nodelist},其中 Nodelist 是此表应具有 disc_only_copies 的节点列表。仅磁盘表副本仅保存在磁盘上,与其他副本类型不同,该副本的内容不驻留在 RAM 中。这些副本比 RAM 中保存的副本慢得多。

  • {index, Intlist},其中 Intlist 是属性名称(原子)或记录字段的列表,Mnesia 将为其构建和维护额外的索引表。如果有可用的索引,qlc 查询编译器可能能够优化查询。

  • {load_order, Integer}。加载顺序优先级默认为 0 (零),但可以设置为任何整数。启动时,具有最高加载顺序优先级的表会首先加载。

  • {majority, Flag},其中 Flag 必须是布尔值。如果 true,除非大多数表副本可用于提交,否则任何对表的(非脏)更新都会中止。在分片表上使用时,所有片段都具有相同的 majority 设置。

  • {ram_copies, Nodelist},其中 Nodelist 是此表应具有 RAM 副本的节点列表。类型为 ram_copies 的表副本不会在每个事务的基础上写入磁盘。 可以使用函数 mnesia:dump_tables(Tabs)ram_copies 副本转储到磁盘。此属性的默认值为 [node()]

  • {record_name, Name},其中 Name 必须是原子。存储在表中的所有记录都必须以此名称作为第一个元素。它默认为与表名称相同的名称。

  • {snmp, SnmpStruct}。有关 SnmpStruct 的描述,请参阅 mnesia:snmp_open_table/2。如果此属性出现在 mnesia:create_table/2ArgList 中,则该表可以通过 SNMP 立即访问。因此,使用 SNMP 来操作和控制系统的应用程序可以轻松设计,因为 Mnesia 提供了构成 SNMP 控制应用程序的逻辑表和构成 Mnesia 表的物理数据之间的直接映射。

  • {storage_properties, [{Backend, Properties}] 将更多属性转发到后端存储。 Backend 当前可以是 etsdetsProperties 是在表创建期间发送到后端存储的选项列表。 Properties 不能包含 Mnesia 已经使用的属性,例如 typenamed_table

    例如:

    mnesia:create_table(table, [{ram_copies, [node()]}, {disc_only_copies, nodes()},
           {storage_properties,
            [{ets, [compressed]}, {dets, [{auto_save, 5000}]} ]}])
  • {type, Type},其中 Type 必须是原子 setordered_setbag 中的一个。默认值为 set。在 set 中,所有记录都具有唯一的键。在 bag 中,多个记录可以具有相同的键,但记录内容是唯一的。如果存储了非唯一记录,则会覆盖旧的冲突记录。

    请注意,目前 ordered_set 不支持 disc_only_copies

  • {local_content, Bool},其中 Booltruefalse。默认值为 false

例如,以下调用将创建 person 表(如前定义)并在两个节点上复制它

mnesia:create_table(person,
    [{ram_copies, [N1, N2]},
     {attributes, record_info(fields, person)}]).

如果需要 Mnesia 在插入到表中的所有 person 记录的属性 address 上构建和维护一个额外的索引表,则会发出以下代码:

mnesia:create_table(person,
    [{ram_copies, [N1, N2]},
     {index, [address]},
     {attributes, record_info(fields, person)}]).

indexattributes 的规范可以硬编码为 {index, [2]}{attributes, [name, age, address, salary, children]},分别。

mnesia:create_table/2 将记录写入 schema 表。此函数以及所有其他 schema 操作函数都是通过正常的事务管理系统实现的。这保证了 schema 更新以原子方式在所有节点上执行。

链接到此函数

deactivate_checkpoint(Name)

查看源代码
-spec deactivate_checkpoint(Name :: _) -> result().

停用检查点。

当涉及的某些表没有附加的保留器时,检查点会自动停用。当节点关闭或删除副本时,可能会发生这种情况。检查点也会通过此函数停用。 Name 是活动检查点的名称。

链接到此函数

del_table_copy(Tab, N)

查看源代码
-spec del_table_copy(Tab :: table(), N :: node()) -> t_result(ok).

删除表的副本。

删除节点 Node 上表 Tab 的副本。当使用此函数删除最后一个副本时,该表将完全消失。

此函数也可用于删除名为 schema 的表的副本。然后会删除 Mnesia 节点。请注意,必须先在节点上停止 Mnesia。

链接到此函数

del_table_index(Tab, I)

查看源代码
-spec del_table_index(Tab, I) -> t_result(ok) when Tab :: table(), I :: index_attr().

删除表索引。

删除表中名称为 AttrName 的属性的索引。

-spec delete(TabKey :: {Tab :: table(), Key :: term()}) -> ok.

等效于 delete(Tab, Key, write)

链接到此函数

delete(Tab, Key, LockKind)

查看源代码
-spec delete(Tab :: table(), Key :: _, LockKind :: write_locks()) -> ok.

删除表 Tab 中具有键 Key 的所有记录。

此函数的语义是上下文相关的。有关详细信息,请参阅 mnesia:activity/4。在事务上下文中,它在记录中获取类型为 LockKind 的锁。目前,支持锁类型 writesticky_write

-spec delete_object(Rec :: tuple()) -> ok.

等效于 delete_object(Tab, Key, write)

链接到此函数

delete_object(Tab, Rec, LockKind)

查看源代码
-spec delete_object(Tab :: table(), Rec :: tuple(), LockKind :: write_locks()) -> ok.

删除记录。

如果表类型为 bag,有时可能需要仅删除具有特定键的某些记录。这可以使用函数 delete_object/3 完成。必须向此函数提供完整的记录。

此函数的语义是上下文相关的。详情请参阅 mnesia:activity/4。在事务上下文中,它会在记录上获取 LockKind 类型的锁。目前,支持的锁类型为 writesticky_write

-spec delete_schema(Ns :: [node()]) -> result().

删除给定节点上的模式。

删除使用 mnesia:create_schema/1 创建的数据库。如果作为 DiscNodes 给出的任何 Erlang 节点未处于活动状态,或者 Mnesia 在任何节点上正在运行,则 mnesia:delete_schema/1 将会失败。

删除数据库后,仍然可以启动 Mnesia 作为无盘节点。这取决于配置参数 schema_location 的设置方式。

警告

请极其谨慎地使用此函数,因为它会使现有的持久数据过时。在使用它之前请三思。

-spec delete_table(Tab :: table()) -> t_result(ok).

永久删除表 Tab 的所有副本。

-spec dirty_all_keys(Tab :: table()) -> [Key :: term()].

mnesia:all_keys/1 等效的脏读取操作。

-spec dirty_delete({Tab :: table(), Key :: _}) -> ok.

等效于 dirty_delete/2

链接到此函数

dirty_delete(Tab, Key)

查看源代码
-spec dirty_delete(Tab :: table(), Key :: _) -> ok.

mnesia:delete/3 等效的脏读取操作。

链接到此函数

dirty_delete_object(Record)

查看源代码
-spec dirty_delete_object(Record :: tuple()) -> ok.

等效于 dirty_delete_object/2

链接到此函数

dirty_delete_object(Tab, Record)

查看源代码
-spec dirty_delete_object(Tab :: table(), Record :: tuple()) -> ok.

mnesia:delete_object/3 等效的脏读取操作。

-spec dirty_first(Tab :: table()) -> Key :: term().

返回表中第一条记录的键。

setbag 表中的记录是无序的。但是,记录之间存在用户未知的顺序。因此,可以通过此函数使用 mnesia:dirty_next/2 来遍历表。

如果表中没有记录,则此函数返回原子 '$end_of_table'。因此,使用此原子作为任何用户记录的键是非常不希望的,但不被禁止。

链接到此函数

dirty_index_match_object(Pattern, Attr)

查看源代码
-spec dirty_index_match_object(Pattern, Attr) -> [Record]
                                  when Pattern :: tuple(), Attr :: index_attr(), Record :: tuple().

等效于 dirty_index_match_object/3

链接到此函数

dirty_index_match_object(Tab, Pattern, Attr)

查看源代码
-spec dirty_index_match_object(Tab, Pattern, Attr) -> [Record]
                                  when
                                      Tab :: table(),
                                      Pattern :: tuple(),
                                      Attr :: index_attr(),
                                      Record :: tuple().

mnesia:index_match_object/4 等效的脏读取操作。

链接到此函数

dirty_index_read(Tab, Key, Attr)

查看源代码
-spec dirty_index_read(Tab, Key, Attr) -> [Record]
                          when Tab :: table(), Key :: term(), Attr :: index_attr(), Record :: tuple().

mnesia:index_read/3 等效的脏读取操作。

-spec dirty_last(Tab :: table()) -> Key :: term().

返回表中最后一条记录的键。

其工作方式与 mnesia:dirty_first/1 完全相同,但对于 ordered_set 表类型,它会返回 Erlang 术语顺序中的最后一个对象。对于所有其他表类型,mnesia:dirty_first/1mnesia:dirty_last/1 是同义词。

链接到此函数

dirty_match_object(Pattern)

查看源代码
-spec dirty_match_object(Pattern :: tuple()) -> [Record :: tuple()].

等效于 dirty_match_object/2

链接到此函数

dirty_match_object(Tab, Pattern)

查看源代码
-spec dirty_match_object(Tab, Pattern) -> [Record]
                            when Tab :: table(), Pattern :: tuple(), Record :: tuple().

mnesia:match_object/3 等效的脏读取操作。

-spec dirty_next(Tab :: table(), Key :: _) -> NextKey :: term().

返回表中的下一个键。

遍历表并对表中的所有记录执行操作。当到达表末尾时,会返回特殊键 '$end_of_table'。否则,该函数会返回一个可用于读取实际记录的键。如果另一个 Erlang 进程在使用函数 mnesia:dirty_next/2 遍历表时对表执行写入操作,则行为是未定义的。

-spec dirty_prev(Tab :: table(), Key :: _) -> PrevKey :: term().

返回表中的上一个键。

其工作方式与 mnesia:dirty_next/2 完全相同,但对于 ordered_set 表类型,它会返回 Erlang 术语顺序中的上一个对象。对于所有其他表类型,mnesia:dirty_next/2mnesia:dirty_prev/2 是同义词。

-spec dirty_read(TabKey :: {Tab :: table(), Key :: _}) -> [tuple()].

等效于 dirty_read(Tab, Key)

-spec dirty_read(Tab :: table(), Key :: _) -> [tuple()].

mnesia:read/3 等效的脏读取操作。

链接到此函数

dirty_select(Tab, Spec)

查看源代码
-spec dirty_select(Tab, Spec) -> [Match] when Tab :: table(), Spec :: ets:match_spec(), Match :: term().

mnesia:select/2 等效的脏读取操作。

链接到此函数

dirty_update_counter/2

查看源代码
-spec dirty_update_counter({Tab :: table(), Key :: _}, Incr :: integer()) -> NewVal :: integer().

等效于 dirty_update_counter/3

链接到此函数

dirty_update_counter(Tab, Key, Incr)

查看源代码
-spec dirty_update_counter(Tab :: table(), Key :: _, Incr :: integer()) -> NewVal :: integer().

对计数器记录进行脏更新。

Mnesia 没有特殊的计数器记录。但是,当 Tabset 时,形式为 {Tab, Key, Integer} 的记录可以用作(可能是驻留在磁盘上的)计数器。此函数使用正数或负数更新计数器。但是,计数器永远不会小于零。此函数与首先读取记录、执行算术运算,然后写入记录的操作之间存在两个显着差异

如果两个进程同时执行 mnesia:dirty_update_counter/3,则两个更新都会生效,而不会有丢失其中一个更新的风险。返回计数器的新值 NewVal

如果 Key 不存在,则创建一个新记录,如果 Incr 大于 0,则其值为 Incr,否则设置为 0。

-spec dirty_write(Record :: tuple()) -> ok.

等效于 dirty_write(Tab, Record)

链接到此函数

dirty_write(Tab, Record)

查看源代码
-spec dirty_write(Tab :: table(), Record :: tuple()) -> ok.

mnesia:write/3 等效的脏读取操作。

-spec dump_log() -> dumped.

执行用户发起的本地日志文件转储。

这通常是不必要的,因为 Mnesia 默认情况下会自动管理此操作。请参阅配置参数 dump_log_time_thresholddump_log_write_threshold

-spec dump_tables([Tab :: table()]) -> t_result(ok).

将 ram_copies 表转储到磁盘。

将一组 ram_copies 表转储到磁盘。下次系统启动时,这些表将使用此转储的结果文件中找到的数据进行初始化。这些表都不能有驻留在磁盘上的副本。

链接到此函数

dump_to_textfile(File)

查看源代码
-spec dump_to_textfile(File :: file:filename()) -> result() | error.

将本地表转储到文本文件中。

将 Mnesia 系统的所有本地表转储到一个文本文件中,该文件可以编辑(使用普通的文本编辑器),然后使用 mnesia:load_textfile/1 重新加载。仅将此函数用于教育目的。使用其他函数来处理真正的备份。

链接到此函数

error_description(Error)

查看源代码
-spec error_description(Error :: term()) -> string().

返回描述特定 Mnesia 错误的字符串。

所有 Mnesia 事务(包括所有模式更新函数)都会返回值 {atomic, Val} 或元组 {aborted, Reason}Reason 可以是以下列表中的任何原子。函数 error_description/1 返回描述错误的描述性字符串。

  • nested_transaction。在此上下文中不允许嵌套事务。
  • badarg。错误或无效的参数,可能是错误的类型。
  • no_transaction。不允许在事务外部进行操作。
  • combine_error。表选项非法组合。
  • bad_index。索引已存在或超出范围。
  • already_exists。要激活的模式选项已启用。
  • index_exists。某些操作无法在带有索引的表上执行。
  • no_exists。尝试对不存在(未激活)的项目执行操作。
  • system_limit。系统限制已耗尽。
  • mnesia_down。事务涉及远程节点上的记录,该节点在事务完成之前变得不可用。记录在网络中的其他地方不再可用。
  • not_a_db_node。提到了架构中不存在的节点。
  • bad_type。参数中指定了错误的类型。
  • node_not_running。节点未运行。
  • truncated_binary_file。文件中二进制文件被截断。
  • active。某些删除操作要求删除所有活动记录。
  • illegal。此记录不支持的操作。

Error 可以是 Reason{error, Reason}{aborted, Reason}Reason 可以是原子或以 Reason 作为第一个字段的原子元组。

以下示例说明了一个返回错误的函数,以及检索更详细的错误信息的方法

  • 函数 [mnesia:create_table(bar, [{attributes, 3.14}])](create_table/2) 返回元组 {aborted,Reason},其中 Reason 是元组 {bad_type,bar,3.14000}
  • 函数 mnesia:error_description(Reason) 返回术语 {"Bad type on some provided arguments",bar,3.14000},这是一个适合显示的错误描述。
-spec ets(Fun) -> Res | no_return() when Fun :: fun(() -> Res).

等效于 ets(Fun, [])

-spec ets(Fun, [Arg :: _]) -> Res | no_return() when Fun :: fun((...) -> Res).

在不受事务保护的原始上下文中调用 Fun

Mnesia 函数调用在 Fun 中执行,并直接在本地 ETS 表上执行,假设本地存储类型为 ram_copies,并且这些表未复制到其他节点。不会触发订阅,也不会更新检查点,但速度非常快。如果所有操作都是只读的,此函数也可以应用于 disc_copies 表。有关详细信息,请参阅 mnesia:activity/4 和用户指南。

请注意,在事务上下文中调用(嵌套)mnesia:ets 会继承事务语义。

-spec first(Tab :: table()) -> Key :: term().

返回表中第一条记录的键。

setbag 表中的记录是无序的。但是,记录之间存在用户未知的顺序。因此,可以使用此函数通过函数 mnesia:next/2 来遍历表。

如果表中没有记录,则此函数返回原子 '$end_of_table'。因此,使用此原子作为任何用户记录的键是非常不希望的,但不被禁止。

-spec foldl(Fun, Acc0, Tab :: table()) -> Acc when Fun :: fun((Record :: tuple(), Acc0) -> Acc).

等效于 foldl(Fun, Acc0, Tab, read)

链接到此函数

foldl(Fun, Acc0, Tab, LockKind)

查看源代码
-spec foldl(Fun, Acc0, Tab :: table(), LockKind :: lock_kind()) -> Acc
               when Fun :: fun((Record :: tuple(), Acc0) -> Acc).

Table 中的每条记录调用 Fun

迭代表 Table,并为表中的每个 Record 调用 Function(Record, NewAcc)。从 Function 返回的术语用作下次调用 Function 的第二个参数。

foldl 返回与最后一次调用 Function 返回的术语相同的术语。

-spec foldr(Fun, Acc0, Tab :: table()) -> Acc when Fun :: fun((Record :: tuple(), Acc0) -> Acc).

等效于 foldr(Fun, Acc0, Tab, read)

链接到此函数

foldr(Fun, Acc0, Tab, LockKind)

查看源代码
-spec foldr(Fun, Acc0, Tab :: table(), LockKind :: lock_kind()) -> Acc
               when Fun :: fun((Record :: tuple(), Acc0) -> Acc).

Table 中的每条记录调用 Fun

其工作方式与 foldl/3 完全相同,但对于 ordered_set 表类型,它会以相反的顺序迭代表。对于所有其他表类型,foldr/3foldl/3 是同义词。

-spec force_load_table(Tab :: table()) -> yes | {error, Reason :: term()}.

强制将表加载到系统中。

Mnesia 的表加载算法可能会导致无法加载表的情况。当节点启动并且 Mnesia 断定或怀疑此本地副本因系统崩溃而变得不活动后,该表的另一个副本处于活动状态时,会出现这种情况。

如果这种情况不可接受,则可以使用此函数来覆盖 Mnesia 表加载算法的策略。这可能导致某些事务效果丢失,并导致数据库不一致,但对于某些应用程序,高可用性比一致数据更重要。

链接到此函数

index_match_object(Pattern, Attr)

查看源代码
-spec index_match_object(Pattern, Attr) -> [Record]
                            when Pattern :: tuple(), Attr :: index_attr(), Record :: tuple().

匹配记录并使用索引信息。

启动 mnesia:index_match_object(Tab, Pattern, Pos, read),其中 Tabelement(1, Pattern)

链接到此函数

index_match_object(Tab, Pattern, Attr, LockKind)

查看源代码
-spec index_match_object(Tab, Pattern, Attr, LockKind) -> [Record]
                            when
                                Tab :: table(),
                                Pattern :: tuple(),
                                Attr :: index_attr(),
                                LockKind :: lock_kind(),
                                Record :: tuple().

匹配记录并使用索引信息。

以类似于函数 mnesia:index_read/3 的方式,尝试匹配记录时可以使用任何索引信息。此函数采用遵循与函数 mnesia:match_object/3 相同的规则的模式,但此函数需要满足以下条件

  • Tab 必须在位置 Pos 上有索引。
  • Pattern 中位置 Pos 的元素必须是绑定的。Pos 是一个整数 (#record.Field) 或属性名称。

此处描述的两个索引搜索函数在搜索带有 qlc 列表推导的表以及使用底层 mnesia:[dirty_]match_object 函数时自动启动。

此函数的语义是上下文相关的。详情请参阅 mnesia:activity/4。在事务上下文中,它会在整个表或单个记录上获取 LockKind 类型的锁。目前,支持的锁类型为 read

链接到此函数

index_read(Tab, Key, Attr)

查看源代码
-spec index_read(Tab, Key, Attr) -> [Record]
                    when Tab :: table(), Key :: term(), Attr :: index_attr(), Record :: tuple().

通过索引表读取记录。

假设某个记录类型的 Pos 位置存在索引。此函数可用于读取记录,而无需知道记录的实际键。例如,对于表 person 中位置 1 的索引,调用 mnesia:index_read(person, 36, #person.age) 会返回所有年龄为 36 的人的列表。Pos 也可以是属性名称(原子),但如果使用 mnesia:index_read(person, 36, age) 表示法,则会在运行时为每次调用搜索字段位置。

此函数的语义是上下文相关的。详情请参阅 mnesia:activity/4。在事务上下文中,它会在整个表上获取读锁。

-spec info() -> ok.

在终端上打印系统信息。

在终端上打印系统信息。即使 Mnesia 未启动,也可以使用此函数。但是,如果 Mnesia 已启动,则会显示更多信息。

-spec install_fallback(Src :: term()) -> result().

等效于 install_fallback(Opaque, [{scope, global}])

链接到此函数

install_fallback(Src, Mod)

查看源代码
-spec install_fallback(Src :: term(), Mod :: module() | [Opt]) -> result()
                          when
                              Opt :: Module | Scope | Dir,
                              Module :: {module, Mod :: module()},
                              Scope :: {scope, global | local},
                              Dir :: {mnesia_dir, Dir :: string()}.

安装一个备份作为回退。

回退用于在下次启动时恢复数据库。安装回退需要所有相关节点上的 Erlang 处于运行状态,但 Mnesia 是否正在运行并不重要。如果本地节点不是备份中的磁盘驻留节点之一,则回退安装将失败。

Args 是以下元组的列表

  • {module, BackupMod}。所有对备份介质的访问都通过名为 BackupMod 的回调模块执行。参数 Opaque 会被转发到回调模块,该模块可以按照自己的意愿解释该参数。默认的回调模块名为 mnesia_backup,它将参数 Opaque 解释为本地文件名。此模块的默认设置也可以通过配置参数 -mnesia mnesia_backup 进行配置。

  • {scope, Scope}。回退的 Scope 可以是 global(针对整个数据库)或 local(针对一个节点)。默认情况下,回退的安装是全局操作,它要么在所有具有磁盘驻留模式的节点上执行,要么在任何节点都不执行。哪些节点是磁盘驻留节点取决于备份中的模式信息。

    如果操作的 Scopelocal,则回退仅安装在本地节点上。

  • {mnesia_dir, AlternateDir}。仅当安装的范围为 local 时,此参数才有效。通常,回退的安装目标是 Mnesia 目录,该目录通过配置参数 -mnesia dir 配置。但是,通过显式提供 AlternateDir,回退将安装在该目录中,而无需考虑 Mnesia 目录配置参数的设置。在备用 Mnesia 目录上安装回退后,该目录已完全准备好用作活动的 Mnesia 目录。

    这是一项危险的功能,必须谨慎使用。如果将同一备份安装到多个目录中,则由于意外混合目录,您很容易最终得到不一致的数据库。

-spec is_transaction() -> boolean().

如果在事务上下文中则返回 true。

当此函数在事务上下文中执行时,它返回 true,否则返回 false

-spec last(Tab :: table()) -> Key :: term().

返回表中最后一条记录的键。

mnesia:first/1 的工作方式完全相同,但对于 ordered_set 表类型,它返回 Erlang 项顺序中的最后一个对象。对于所有其他表类型,mnesia:first/1mnesia:last/1 是同义词。

-spec load_textfile(File :: file:filename()) -> t_result(ok) | {error, term()}.

从文本文件加载表。

将文本文件(使用 mnesia:dump_to_textfile/1 生成)中的一系列定义和数据加载到 Mnesia 中。此函数还会启动 Mnesia,并可能创建一个新的模式。此函数仅用于教育目的。建议使用其他函数来处理实际备份。

链接到此函数

lock(LockItem, LockKind)

查看源代码
-spec lock(LockItem, LockKind) -> list() | tuple() | no_return()
              when
                  LockItem ::
                      {record, table(), Key :: term()} |
                      {table, table()} |
                      {global, Key :: term(), MnesiaNodes :: [node()]},
                  LockKind :: lock_kind() | load.

显式获取锁。

通常在表副本所在的(且处于活动状态的)所有节点上获取写锁。在单个节点(如果存在本地副本,则为本地节点)上获取读锁。如果上下文相关的访问函数在事务上下文中启动,则大多数上下文相关的访问函数会获取隐式锁。锁的粒度可以是单个记录或整个表。

通常的用法是不检查返回值就调用该函数,因为它会在失败时退出,并且事务会由事务管理器重新启动。如果获取了写锁,则返回所有被锁定的节点,如果获取的是读锁,则返回 ok

函数 mnesia:lock/2 旨在支持在表上进行显式锁定,但也适用于需要获取锁的情况,而无需考虑表是如何复制的。目前,支持两种 LockKind

  • write - 写锁是互斥的。这意味着如果一个事务设法在某个项上获取写锁,则没有其他事务可以在同一项上获取任何类型的锁。

  • read - 读锁可以共享。这意味着如果一个事务设法在某个项上获取读锁,则其他事务也可以在同一项上获取读锁。但是,如果某人拥有读锁,则没有人可以在同一项上获取写锁。如果某人拥有写锁,则没有人可以在同一项上获取读锁或写锁。

如果没有死锁风险,则冲突的锁请求会自动排队。否则,必须终止事务并再次执行。只要未达到最大 retries 的上限,Mnesia 就会自动执行此操作。有关详细信息,请参阅 mnesia:transaction/3

为了完整起见,此处还描述了粘性写锁,即使此函数不支持粘性写锁。

  • sticky_write - 粘性写锁是一种可用于优化写锁获取的机制。如果您的应用程序主要使用复制表来实现容错(而不是出于读取访问优化目的),则粘性锁可能是最佳选择。

    获取粘性写锁时,会通知所有节点哪个节点被锁定。然后,来自同一节点的粘性锁请求将作为本地操作执行,而无需与其他节点进行任何通信。即使事务结束,粘性锁仍会保留在该节点上。有关详细信息,请参阅用户指南。

目前,此函数支持两种 LockItem

  • {table, Tab} - 这将在整个表 Tab 上获取 LockKind 类型的锁。

  • {global, GlobalKey, Nodes} - 这将在全局资源 GlobalKey 上获取 LockKind 类型的锁。该锁会在 Nodes 列表中的所有活动节点上获取。

当最外层的事务结束时,锁将被释放。

此函数的语义是上下文相关的。有关详细信息,请参阅 mnesia:activity/4。在事务上下文中,它会获取锁,否则会忽略该请求。

-spec match_object(Pattern :: tuple()) -> [Record :: tuple()].

等效于 match_object(Tab, Pattern, read)

链接到此函数

match_object(Tab, Pattern, LockKind)

查看源代码
-spec match_object(Tab, Pattern, LockKind) -> [Record]
                      when
                          Tab :: table(), Pattern :: tuple(), LockKind :: lock_kind(), Record :: tuple().

为记录匹配 Pattern

获取一个带有“无关”变量(表示为 '_' 参数)的模式。此函数返回与该模式匹配的记录列表。由于表中的记录的第二个元素被认为是该记录的键,因此此函数的性能取决于此键是否已绑定。

例如,调用 mnesia:match_object(person, {person, '_', 36, '_', '_'}, read) 会返回所有 age 字段为 36 的人员记录的列表。

如果存在索引,则函数 mnesia:match_object/3 会自动使用索引。但是,不会执行任何启发式方法来选择最佳索引。

此函数的语义是上下文相关的。有关详细信息,请参阅 mnesia:activity/4。在事务上下文中,它会在整个表或单个记录上获取 LockKind 类型的锁。目前,支持锁类型 read

链接到此函数

move_table_copy(Tab, From, To)

查看源代码
-spec move_table_copy(Tab :: table(), From :: node(), To :: node()) -> t_result(ok).

移动表副本。

将表 Tab 的副本从节点 From 移动到节点 To

存储类型将保留。例如,从一个节点移动的 RAM 表在新节点上仍然是 RAM 表。在移动表的过程中,其他事务仍然可以在表中读取和写入。

此函数不能用于 local_content 表。

-spec next(Tab :: table(), Key :: term()) -> NextKey :: term().

返回表中的下一个键。

遍历一个表并在该表中的所有记录上执行操作。到达表尾时,将返回特殊键 '$end_of_table'。否则,该函数将返回一个可用于读取实际记录的键。

-spec prev(Tab :: table(), Key :: term()) -> PrevKey :: term().

返回表中的上一个键。

mnesia:next/2 的工作方式完全相同,但对于 ordered_set 表类型,它返回 Erlang 项顺序中的上一个对象。对于所有其他表类型,mnesia:next/2mnesia:prev/2 是同义词。

-spec read(TabKey :: {Tab :: table(), Key :: _}) -> [tuple()].

等效于 read(Tab, Key, read)

-spec read(Tab :: table(), Key :: _) -> [tuple()].

等效于 read(Tab, Key, read)

链接到此函数

read(Tab, Key, LockKind)

查看源代码
-spec read(Tab :: table(), Key :: _, LockKind :: lock_kind()) -> [tuple()].

读取具有给定键的记录。

从键为 Key 的表 Tab 中读取所有记录。此函数具有相同的语义,而无需考虑 Tab 的位置。如果表类型为 bag,则函数 mnesia:read(Tab, Key) 可以返回任意长的列表。如果表类型为 set,则列表的长度为 1 或 []

此函数的语义是上下文相关的。有关详细信息,请参阅 mnesia:activity/4。在事务上下文中,它会获取 LockKind 类型的锁。目前,支持锁类型 readwritesticky_write

如果用户想要更新记录,则将 write/sticky_write 用作 LockKind 会更有效率。如果表中启用了多数检查,则会在尝试获取写锁时立即检查。如果未满足多数条件,则可以使用它来快速结束。

-spec read_lock_table(Tab :: table()) -> ok.

等效于 lock({table, Tab}, read)

-spec report_event(Event :: _) -> ok.

向 Mnesia 事件处理程序报告用户事件。

在跟踪 Mnesia 应用程序的系统时,能够将 Mnesia 自己的事件与提供有关应用程序上下文信息的应用程序相关事件交错使用会很有用。

每当应用程序开始一项新的且要求很高的 Mnesia 任务时,或者当它进入执行中的一个新有趣阶段时,使用 mnesia:report_event/1 可能是一个好主意。Event 可以是任何项,并且会为订阅 Mnesia 系统事件的任何进程生成一个 {mnesia_user, Event} 事件。

-spec restore(Src :: _, [Arg]) -> t_result([table()])
                 when
                     Op :: skip_tables | clear_tables | keep_tables | restore_tables,
                     Arg :: {module, module()} | {Op, [table()]} | {default_op, Op}.

恢复备份。

使用此函数,可以从备份在线还原表,而无需重新启动 Mnesia。Opaque 将被转发到备份模块。Args 是以下元组的列表:

  • {module,BackupMod}。备份模块 BackupMod 用于访问备份介质。如果省略,则使用默认的备份模块。
  • {skip_tables, TabList},其中 TabList 是不从备份中读取的表列表。
  • {clear_tables, TabList},其中 TabList 是在插入备份中的记录之前要清除的表列表。也就是说,在还原表之前,会删除表中的所有记录。不会清除或从备份中读取有关表的模式信息。
  • {keep_tables, TabList},其中 TabList 是在插入备份中的记录之前不清除的表列表。也就是说,备份中的记录会添加到表中的记录中。不会清除或从备份中读取有关表的模式信息。
  • {recreate_tables, TabList},其中 TabList 是一个表列表,在插入备份记录之前需要重新创建这些表。这些表会先被删除,然后使用备份中的模式信息重新创建。备份中的所有节点都需要处于运行状态。
  • {default_op, Operation},其中 Operationskip_tablesclear_tableskeep_tablesrecreate_tables 操作之一。默认操作指定对备份中未在任何上述列表中指定的表执行的操作。如果省略,则使用 clear_tables 操作。

受影响的表在恢复期间会被写入锁定。但是,无论由此导致的锁定冲突如何,应用程序都可以在执行恢复时继续其工作。恢复是作为一个单独的事务执行的。

如果数据库非常庞大,则不总是可以进行在线恢复。在这种情况下,通过安装回退并重新启动来恢复旧数据库。

-spec s_delete(TabKey :: {Tab :: table(), Key :: _}) -> ok.

调用函数 mnesia:delete(Tab, Key, sticky_write)

-spec s_delete_object(Rec :: tuple()) -> ok.

等效于 delete_object(element(1, Rec), Rec, sticky_write)

-spec s_write(Record :: tuple()) -> ok.

等效于 write(Tab, Val, sticky_write)

-spec schema() -> ok.

在终端上打印有关所有表定义的信息。

-spec schema(Tab :: table()) -> ok.

在终端上打印有关一个表定义的信息。

-spec select(Cont) -> {[Match], Cont} | '$end_of_table'
                when Match :: term(), Cont :: select_continuation().

继续选择对象。

使用由 mnesia:select/4 发起的匹配规范选择更多对象。

请注意,在 mnesia:select/4mnesia:select/1 调用之间进行的任何修改操作,即 mnesia:writemnesia:delete,在结果中都不可见。

链接到此函数

select(Tab, MatchSpec)

查看源代码
-spec select(Tab, MatchSpec) -> [Match]
                when Tab :: table(), MatchSpec :: ets:match_spec(), Match :: term().

等效于 select(Tab, MatchSpec, read)

链接到此函数

select(Tab, Spec, LockKind)

查看源代码
-spec select(Tab, Spec, LockKind) -> [Match]
                when Tab :: table(), Spec :: ets:match_spec(), Match :: term(), LockKind :: lock_kind().

根据 MatchSpec 选择 Tab 中的对象。

使用 ets:select/3 中描述的 match_spec 匹配表 Tab 中的对象。可选地,可以将锁 readwrite 作为第三个参数给出。默认为 read。返回值取决于 MatchSpec

请注意,为了获得最佳性能,select 应该在同一事务中对该表进行任何修改操作之前使用。也就是说,在 select 之前不要使用 writedelete

在其最简单的形式中,match_spec 如下所示

  • MatchSpec = [MatchFunction]
  • MatchFunction = {MatchHead, [Guard], [Result]}
  • MatchHead = tuple() | record()

  • Guard = {"Guardtest name", ...}
  • Result = "Term construct"

有关 select 的完整描述,请参阅 ERTS 用户指南和 STDLIB 中的 ets 手册页。

例如,要在表 Tab 中查找所有 30 岁以上的男性人员的姓名

MatchHead = #person{name='$1', sex=male, age='$2', _='_'},
Guard = {'>', '$2', 30},
Result = '$1',
mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),
链接到此函数

select(Tab, Spec, N, LockKind)

查看源代码
-spec select(Tab, Spec, N, LockKind) -> {[Match], Cont} | '$end_of_table'
                when
                    Tab :: table(),
                    Spec :: ets:match_spec(),
                    Match :: term(),
                    N :: non_neg_integer(),
                    LockKind :: lock_kind(),
                    Cont :: select_continuation().

根据 MatchSpec 选择 Tab 中的对象。

使用 ERTS 用户指南中描述的 match_spec 匹配表 Tab 中的对象,并返回一个术语块和一个延续。返回的术语的数量由参数 NObjects 指定。锁参数可以是 readwrite。如果需要更多或所有答案,则延续将用作 mnesia:select/1 的参数。

请注意,为了获得最佳性能,select 应该在同一事务中对该表进行任何修改操作之前使用。也就是说,在 mnesia:select 之前不要使用 mnesia:writemnesia:delete。为了提高效率,NObjects 仅为建议值,结果可能包含从空列表到所有可用结果的任何内容。

链接到此函数

set_debug_level(Level)

查看源代码
-spec set_debug_level(Level :: debug_level()) -> OldLevel :: debug_level().

更改 Mnesia 的内部调试级别。

有关详细信息,请参阅配置参数](mnesia) 部分。

-spec set_master_nodes(Ns :: [node()]) -> result().

设置所有表的主节点。

对于每个表,Mnesia 确定其副本节点 (TabNodes) 并启动 mnesia:set_master_nodes(Tab, TabMasterNodes)。其中 TabMasterNodesMasterNodesTabNodes 的交集。有关语义,请参阅 mnesia:set_master_nodes/2

链接到此函数

set_master_nodes(Tab, Ns)

查看源代码
-spec set_master_nodes(Tab :: table(), Ns :: [node()]) -> result().

设置一个表的主节点。

如果应用程序检测到可能导致数据库不一致的通信故障(在可能发生分区的网络中),则可以使用函数 mnesia:set_master_nodes(Tab, MasterNodes) 来定义从哪些节点加载每个表。在启动时,Mnesia 正常的表加载算法会被绕过,并且该表会从为该表定义的主节点之一加载,无论 Mnesia 何时以及是否在其他节点上终止。MasterNodes 只能包含该表具有副本的节点。如果 MasterNodes 列表为空,则特定表的主节点恢复机制将被重置,并且在下次重新启动时使用正常的加载机制。

主节点设置始终是本地的。无论 Mnesia 是否启动,都可以更改它。

如果使用配置参数 max_wait_for_decision 或使用 mnesia:force_load_table/1,数据库也可能变得不一致。

-spec snmp_close_table(Tab :: table()) -> ok.

移除 SNMP 操作表的可能性。

链接到此函数

snmp_get_mnesia_key(Tab, RowIndex)

查看源代码
-spec snmp_get_mnesia_key(Tab :: table(), RowIndex :: [integer()]) -> {ok, Key :: term()} | undefined.

从 SNMP 索引获取相应的 Mnesia 键。

将 SNMP 索引转换为相应的 Mnesia 键。如果 SNMP 表有多个键,则该键是键列的元组。

链接到此函数

snmp_get_next_index(Tab, RowIndex)

查看源代码
-spec snmp_get_next_index(Tab :: table(), RowIndex :: [integer()]) -> {ok, [integer()]} | endOfTable.

获取下一个按字典顺序排列的行的索引。

RowIndex 可以指定一个不存在的行。具体而言,它可以是空列表。返回下一个按字典顺序排列的行的索引。如果 RowIndex 是空列表,则此函数返回表中第一行的索引。

链接到此函数

snmp_get_row(Tab, RowIndex)

查看源代码
-spec snmp_get_row(Tab :: table(), RowIndex :: [integer()]) -> {ok, Row :: tuple()} | undefined.

检索由 SNMP 索引索引的行。

通过其 SNMP 索引读取一行。此索引指定为 SNMP 对象标识符,一个整数列表。

链接到此函数

snmp_open_table(Tab, Snmp)

查看源代码
-spec snmp_open_table(Tab :: table(), Snmp :: snmp_struct()) -> ok.

将 Mnesia 表组织为 SNMP 表。

可以在 Mnesia 表和 SNMP 表之间建立直接的一对一映射。许多电信应用程序通过 SNMP 协议进行控制和监视。Mnesia 和 SNMP 之间的这种连接使得实现这种映射变得简单方便。

参数 SnmpStruct 是 SNMP 信息列表。当前,唯一需要的信息是表中键类型的信息。Mnesia 中无法处理多个键,但许多 SNMP 表有多个键。因此,使用以下约定:如果一个表有多个键,则这些键必须始终存储为键的元组。键类型的信息指定为描述类型的原子元组。唯一重要的类型是 fix_string。这意味着字符串具有固定大小。

例如,以下内容会导致表 person 按 SNMP 表排序

mnesia:snmp_open_table(person, [{key, string}])

考虑以下公司员工表的架构。每个员工都由部门编号和姓名标识。另一个表列存储电话号码

mnesia:create_table(employee,
    [{snmp, [{key, {integer, string}}]},
     {attributes, record_info(fields, employees)}]),

相应的 SNMP 表将具有三列:departmentnametelno

一个选项是具有 SNMP 协议不可见的表列。这些列必须是表的最后一列。在前面的示例中,SNMP 表可能仅具有 departmentname 列。然后,应用程序可以在内部使用 telno 列,但 SNMP 管理器不可见。

在由 SNMP 监视的表中,所有元素必须是整数、字符串或整数列表。

当表按 SNMP 排序时,修改比平时更昂贵,为 O(logN)。此外,还会使用更多内存。

请注意,Mnesia 中仅实现了词典 SNMP 排序,而不是实际的 SNMP 监视。

-spec start() -> result().

启动本地 Mnesia 系统。

Mnesia 启动是异步的。函数调用 mnesia:start() 返回原子 ok,然后开始初始化不同的表。根据数据库的大小,这可能需要一些时间,应用程序程序员必须在可以使用它们之前等待应用程序需要的表。这可以通过使用函数 mnesia:wait_for_tables/2 来实现。

一组 Mnesia 节点的启动过程是一个相当复杂的操作。Mnesia 系统由一组节点组成,所有参与节点上都在本地启动了 Mnesia。通常,每个节点都有一个目录,其中写入所有 Mnesia 文件。此目录称为 Mnesia 目录。Mnesia 也可以在无盘节点上启动。有关无盘节点的更多信息,请参阅 mnesia:create_schema/1 和用户指南。

构成 Mnesia 系统的节点集保存在模式中。可以将 Mnesia 节点添加到模式中或从模式中删除。初始模式通常使用函数 mnesia:create_schema/1 在磁盘上创建。在无盘节点上,每次启动 Mnesia 时都会生成一个小的默认模式。在启动过程中,Mnesia 会在节点之间交换模式信息,以验证表定义是否兼容。

每个模式都有一个唯一的 cookie,可以将其视为唯一的模式标识符。在所有要运行 Mnesia 的节点上,cookie 必须相同。有关详细信息,请参阅用户指南。

模式文件和 Mnesia 需要的所有其他文件都保存在 Mnesia 目录中。命令行选项 -mnesia dir Dir 可用于向 Mnesia 系统指定此目录的位置。如果找不到这样的命令行选项,则目录的名称默认为 Mnesia.Node

也可以使用 application:start(mnesia)

-spec stop() -> stopped | {error, term()}.

在当前节点本地停止 Mnesia。

也可以使用 application:stop(mnesia)

-spec subscribe(What) -> {ok, node()} | {error, Reason :: term()}
                   when What :: system | activity | {table, table(), simple | detailed}.

订阅 EventCategory 类型的事件。

确保将类型为 EventCategory 的所有事件的副本发送给调用方。有关可用事件类型的描述,请参阅 用户指南

-spec sync_dirty(Fun) -> Res | no_return() when Fun :: fun(() -> Res).

等效于 sync_dirty/2

-spec sync_dirty(Fun, [Arg :: _]) -> Res | no_return() when Fun :: fun((...) -> Res).

在不受事务保护的上下文中调用 Fun

Fun 中执行的 Mnesia 函数调用将映射到相应的脏函数。它的执行上下文与 mnesia:async_dirty/1,2 几乎相同。区别在于操作是同步执行的。调用方会等待更新在所有活动副本上执行完毕,然后 Fun 返回。有关详细信息,请参阅 mnesia:activity/4 和用户指南。

链接到此函数

sync_log()

View Source (自 OTP 17.0 起)
-spec sync_log() -> result().

对本地日志文件执行文件同步。

确保本地事务日志文件已同步到磁盘。在单节点系统上,如果发生断电,可能会丢失自上次转储以来写入磁盘表的数据。请参阅 dump_log/0

-spec sync_transaction(Fun) -> t_result(Res) when Fun :: fun(() -> Res).

等效于 sync_transaction(Fun, [], infinity)

-spec sync_transaction(Fun, Retries) -> t_result(Res)
                          when
                              Fun :: fun(() -> Res) | fun((...) -> Res),
                              Retries :: non_neg_integer() | infinity;
                      (Fun, Args :: [Arg :: _]) -> t_result(Res) when Fun :: fun((...) -> Res).

等效于 sync_transaction/3

链接到此函数

sync_transaction(Fun, Args, Retries)

查看源代码
-spec sync_transaction(Fun, [Arg :: _], Retries) -> t_result(Res)
                          when Fun :: fun((...) -> Res), Retries :: non_neg_integer() | infinity.

同步执行事务。

等待数据在每个涉及的节点上提交并记录到磁盘(如果使用磁盘),然后返回,否则它的行为与 mnesia:transaction/[1,2,3] 相同。

此功能可用于避免一个进程在另一个节点上使数据库过载。

-spec system_info(Iterm :: term()) -> Info :: term().

返回有关 Mnesia 系统的信息。

例如事务统计信息、db_nodes 和配置参数。

有效键如下

  • all。返回所有本地系统信息的列表。每个元素都是一个 {InfoKey, InfoVal} 元组。

    可以在不通知的情况下添加新的 InfoKey 并删除旧的未记录的 InfoKey

  • access_module。返回配置为活动访问回调模块的模块的名称。

  • auto_repair。返回 truefalse 以指示 Mnesia 是否配置为在损坏的磁盘文件上启动自动修复工具。

  • backup_module。返回配置为备份回调模块的模块的名称。

  • checkpoints. 返回当前在此节点上处于活动状态的检查点名称列表。

  • event_module. 返回作为事件处理回调模块的模块名称。

  • db_nodes. 返回构成持久数据库的节点。 无盘节点仅在显式添加到 schema 时才包含在节点列表中,例如,使用 mnesia:add_table_copy/3。 即使 Mnesia 尚未运行,也可以启动此函数。

  • debug. 返回 Mnesia 当前的调试级别。

  • directory. 返回 Mnesia 目录的名称。 即使 Mnesia 尚未运行,也可以调用此函数。

  • dump_log_load_regulation. 返回一个布尔值,指示 Mnesia 是否配置为调节转储进程的负载。

    此功能是临时的,将在未来的版本中删除。

  • dump_log_time_threshold. 返回事务日志转储的时间阈值(以毫秒为单位)。

  • dump_log_update_in_place. 返回一个布尔值,指示 Mnesia 是否配置为直接在 Dets 文件中执行更新,或者是否在 Dets 文件的副本中执行更新。

  • dump_log_write_threshold. 返回事务日志转储的写入阈值,以写入事务日志的次数表示。

  • extra_db_nodes. 返回在启动时要联系的额外 db_nodes 列表。

  • fallback_activated. 如果激活了回退,则返回 true,否则返回 false

  • held_locks. 返回本地 Mnesia 锁管理器持有的所有锁的列表。

  • is_running. 返回 yesno 以指示 Mnesia 是否正在运行。 它也可以返回 startingstopping。 即使 Mnesia 尚未运行,也可以调用此函数。

  • local_tables. 返回配置为驻留在本地的所有表的列表。

  • lock_queue. 返回本地锁管理器排队等待执行的所有事务的列表。

  • log_version. 返回 Mnesia 事务日志格式的版本号。

  • master_node_tables. 返回至少有一个主节点的所有表的列表。

  • protocol_version. 返回 Mnesia 进程间通信协议的版本号。

  • running_db_nodes. 返回 Mnesia 当前正在运行的节点列表。 即使 Mnesia 尚未运行,也可以调用此函数,但其语义略有不同。

    如果本地节点上的 Mnesia 已关闭,则该函数返回那些当前正在运行的其他 db_nodesextra_db_nodes

    如果 Mnesia 已启动,则该函数返回本地节点上的 Mnesia 完全连接到的那些节点。 只有那些 Mnesia 与之交换了 schema 信息的节点才会被包含为 running_db_nodes。 在合并 schema 之后,本地 Mnesia 系统完全可操作,应用程序可以执行远程副本的访问。 在 schema 合并之前,Mnesia 仅在本地运行。 有时,running_db_nodes 列表中包含的节点比所有 db_nodesextra_db_nodes 加起来还要多。

  • schema_location. 返回初始 schema 位置。

  • subscribers. 返回当前订阅系统事件的本地进程列表。

  • tables. 返回所有本地已知的表列表。

  • transactions. 返回所有当前活动的本地事务的列表。

  • transaction_failures. 返回一个数字,指示自 Mnesia 启动以来有多少事务失败。

  • transaction_commits. 返回一个数字,指示自 Mnesia 启动以来有多少事务成功终止。

  • transaction_restarts. 返回一个数字,指示自 Mnesia 启动以来有多少事务已重新启动。

  • transaction_log_writes. 返回一个数字,指示自启动以来已对事务日志执行了多少写入操作。

  • use_dir. 返回一个布尔值,指示是否使用 Mnesia 目录。 即使 Mnesia 尚未运行,也可以启动此函数。

  • version. 返回 Mnesia 的当前版本号。

-spec table(Tab :: table()) -> qlc:query_handle().

等效于 table/2

-spec table(Tab :: table(), Options) -> qlc:query_handle()
               when
                   Options :: Option | [Option],
                   Option :: MnesiaOpt | QlcOption,
                   MnesiaOpt ::
                       {traverse, SelectOp} | {lock, lock_kind()} | {n_objects, non_neg_integer()},
                   SelectOp :: select | {select, ets:match_spec()},
                   QlcOption :: {key_equality, '==' | '=:='}.

返回 QLC 查询句柄。

返回一个查询列表推导 (QLC) 查询句柄,请参阅 STDLIB 中的 qlc 手册页面。 模块 qlc 实现了一种查询语言,该语言可以使用 Mnesia 表作为数据源。 调用 mnesia:table/1,2 是使 mnesiaTab 可用于 QLC 的方法。

Option 可以包含 Mnesia 选项或 QLC 选项。 Mnesia 识别以下选项(任何其他选项都将转发到 QLC)。

  • {lock, Lock},其中 lock 可以是 readwrite。 默认值为 read
  • {n_objects,Number},其中 n_objects 指定(大致)从 Mnesia 返回到 QLC 的对象数量。 对远程表的查询可能需要更大的块来减少网络开销。 默认情况下,一次返回 100 个对象。
  • {traverse, SelectMethod},其中 traverse 确定遍历整个表的方法(如果需要)。 默认方法是 select

对于 select 有两种选择

  • select。 通过调用 mnesia:select/4mnesia:select/1 来遍历表。 匹配规范(select/3 的第二个参数)由 QLC 组装:简单的过滤器会转换为等效的匹配规范。 更复杂的过滤器需要应用于 select/3 返回的所有对象,给定一个与所有对象匹配的匹配规范。
  • {select, MatchSpec}。 与 select 一样,通过调用 mnesia:select/3mnesia:select/1 来遍历表。 不同之处在于,显式给出了匹配规范。 这是如何声明无法在 QLC 提供的语法中轻松表达的匹配规范。
-spec table_info(Tab :: table(), Item :: term()) -> Info :: term().

返回关于表的本地信息。

table_info/2 函数接受两个参数。 第一个是 Mnesia 表的名称。 第二个是以下键之一

  • all。 返回所有本地表信息的列表。 每个元素都是一个 {InfoKey, ItemVal} 元组。

    可以添加新的 InfoItem,并且可以删除旧的未文档化的 InfoItem,恕不另行通知。

  • access_mode。 返回表的访问模式。 访问模式可以是 read_onlyread_write

  • arity。 返回 schema 中指定的表中记录的元数。

  • attributes. 返回 schema 中指定的表属性名称。

  • checkpoints. 返回当前活动的检查点名称,其中涉及此节点上的此表。

  • cookie. 返回一个表 cookie,它是表唯一的系统生成的标识符。 Cookie 在内部用于确保两个使用相同表名的不同表定义不会意外地混合在一起。 Cookie 在最初创建表时生成。

  • disc_copies. 根据 schema 返回表的 disc_copy 所在的节点。

  • disc_only_copies. 根据 schema 返回表的 disc_only_copy 所在的节点。

  • index. 返回表的索引位置整数的列表。

  • load_node. 返回 Mnesia 从中加载表的节点的名称。 返回值的结构未指定,但可能对调试有用。

  • load_order. 返回表的加载顺序优先级。 它是一个整数,默认为 0(零)。

  • load_reason. 返回 Mnesia 决定加载该表的原因。 返回值的结构未指定,但可能对调试有用。

  • local_content. 返回 truefalse 以指示是否配置该表以在每个节点上具有本地唯一内容。

  • master_nodes. 返回表的主节点。

  • memory. 对于 ram_copiesdisc_copies 表,返回在此节点的表中分配的内存字数。 对于 disc_only_copies 表,返回存储在磁盘上的字节数。

  • ram_copies. 根据 schema 返回表的 ram_copy 所在的节点。

  • record_name. 返回表中所有记录通用的记录名称。

  • size. 返回表中插入的记录数。

  • snmp. 返回 SNMP 结构。 [] 表示该表当前没有 SNMP 属性。

  • storage_type. 返回表的本地存储类型。 它可以是 disc_copiesram_copiesdisc_only_copies 或原子 unknownunknown 返回给所有仅驻留在远程的表。

  • subscribers. 返回当前订阅本地表事件的本地进程列表,该事件涉及此节点上的此表。

  • type. 返回表类型,即 bagsetordered_set

  • user_properties. 返回表的用户关联表属性。 它是存储的属性记录的列表。

  • version. 返回表定义的当前版本。 当表定义更改时,表版本会递增。 表定义可以直接在 schema 事务中更改时递增,或者当提交的表定义在启动期间与其他节点的表定义合并时递增。

  • where_to_read. 返回可以读取表的节点。 如果返回值 nowhere,则表示该表未加载或驻留在未运行的远程节点上。

  • where_to_write. 返回当前拥有该表活动副本的节点列表。

  • wild_pattern. 返回一个可以提供给特定表的各种匹配函数的结构。 记录元组是指所有记录字段的值均为 '_' 的元组。

-spec transaction(Fun) -> t_result(Res) when Fun :: fun(() -> Res).

等效于 transaction(Fun, [], infinity)

-spec transaction(Fun, Retries) -> t_result(Res)
                     when Fun :: fun(() -> Res), Retries :: non_neg_integer() | infinity;
                 (Fun, Args :: [Arg :: _]) -> t_result(Res) when Fun :: fun((...) -> Res).

等效于 transaction/3

链接到此函数

transaction(Fun, Args, Retries)

查看源代码
-spec transaction(Fun, [Arg :: _], Retries) -> t_result(Res)
                     when Fun :: fun((...) -> Res), Retries :: non_neg_integer() | infinity.

将带有参数 ArgsFun 作为事务执行。

在事务内执行的代码可以包含一系列的表操作函数。如果由于用户错误或某个表不可用导致事务内部出现问题,整个事务将终止,并且函数 transaction/1 将返回元组 {aborted, Reason}

如果一切顺利,则返回 {atomic, ResultOfFun},其中 ResultOfFunFun 中最后一个表达式的值。

如果存在结构 {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)}.

此代码将一组人员添加到数据库。在一个事务中运行此代码可确保要么将整个家庭添加到数据库,要么终止整个事务。例如,如果最后一个孩子的格式错误,或者执行家庭代码时,执行进程由于 'EXIT' 信号而终止,则事务将终止。因此,永远不会发生只添加了半个家庭的情况。

如果多个进程并发更新相同的记录,在事务中更新数据库也很有用。例如,函数 raise(Name, Amount)Amount 添加到人员的薪资字段,应按如下方式实现:

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).

当此函数在事务中执行时,在不同节点上运行的多个进程可以并发执行函数 raise/2,而不会相互干扰。

由于 Mnesia 检测死锁,事务可以重启任意次数,因此 Fun 不应有任何副作用,例如等待特定消息。此函数尝试重启次数与 Retries 中指定的次数相同。Retries 必须是大于 0 的整数或原子 infinity,默认为 infinity。Mnesia 使用 exit 异常来指示需要重启事务,因此 Fun 不得捕获原因是 {aborted, term()}exit 异常。

链接到此函数

transform_table(Tab, Fun, NewA)

查看源代码
-spec transform_table(Tab :: table(), Fun, [Attr]) -> t_result(ok)
                         when
                             Attr :: atom(),
                             Fun :: fun((Record :: tuple()) -> Transformed :: tuple()) | ignore.

等效于 transform_table(Tab, Fun, NewAttributeList, mnesia:table_info(Tab, record_name))

链接到此函数

transform_table(Tab, Fun, NewA, NewRN)

查看源代码
-spec transform_table(Tab :: table(), Fun, [Attr], RecName) -> t_result(ok)
                         when
                             RecName :: atom(),
                             Attr :: atom(),
                             Fun :: fun((Record :: tuple()) -> Transformed :: tuple()) | ignore.

更改表中所有记录的格式。

将参数 Fun 应用于表中的所有记录。Fun 是一个函数,它接收旧类型的记录并返回新类型的转换记录。参数 Fun 也可以是原子 ignore,表示仅更新有关表的元数据。不建议使用 ignore,但将其作为用户执行自定义转换的可能性而包含在内。

NewAttributeListNewRecordName 指定转换后的表的属性和新的记录类型。表名始终保持不变。如果更改了 record_name,则只有使用表标识符的 Mnesia 函数才起作用,例如,mnesia:write/3 起作用,而 mnesia:write/1 不起作用。

链接到此函数

traverse_backup(Src, Dest, Fun, Acc)

查看源代码
-spec traverse_backup(Src :: term(), Dest :: term(), Fun, Acc) -> {ok, Acc} | {error, Reason :: term()}
                         when Fun :: fun((Items, Acc) -> {Items, Acc}).

等效于 traverse_backup/6

链接到此函数

traverse_backup(Src, SrcMod, Dest, DestMod, Fun, Acc)

查看源代码
-spec traverse_backup(Src :: term(), SrcMod :: module(), Dest :: term(), DestMod :: module(), Fun, Acc) ->
                         {ok, Acc} | {error, Reason :: term()}
                         when Fun :: fun((Items, Acc) -> {Items, Acc}).

遍历备份。

迭代备份,将其转换为新备份或读取它。此处简要说明参数。有关详细信息,请参阅用户指南。

  • SourceModTargetMod 是实际访问备份介质的模块的名称。
  • SourceTarget 是由模块 SourceModTargetMod 专门用于初始化备份介质的不透明数据。
  • Acc 是初始累加器值。
  • Fun(BackupItems, Acc) 应用于备份中的每个项目。Fun 必须返回元组 {BackupItems,NewAcc},其中 BackupItems 是有效备份项的列表,而 NewAcc 是新的累加器值。返回的备份项将写入目标备份中。
  • LastAcc 是最后一个累加器值。这是由 Fun 返回的最后一个 NewAcc 值。
-spec uninstall_fallback() -> result().

等效于 uninstall_fallback([{scope, global}])

链接到此函数

uninstall_fallback(Args)

查看源代码
-spec uninstall_fallback(Args) -> result() when Args :: [{mnesia_dir, Dir :: string()}].

卸载回退。

在回退用于还原数据库之前将其卸载。这通常是一个分布式操作,要么在所有具有磁盘驻留模式的节点上执行,要么都不执行。卸载回退需要 Erlang 在所有相关节点上运行,但 Mnesia 是否正在运行无关紧要。哪些节点被视为磁盘驻留节点由本地回退中的模式信息确定。

Args 是以下元组的列表

-spec unsubscribe(What) -> {ok, node()} | {error, Reason :: term()}
                     when What :: system | activity | {table, table(), simple | detailed}.

停止向调用者发送 EventCategory 类型的事件。

Node 是本地节点。

链接到此函数

wait_for_tables(Tabs, Timeout)

查看源代码
-spec wait_for_tables([Tab :: table()], TMO :: timeout()) -> result() | {timeout, [table()]}.

等待表可访问。

某些应用程序需要等待某些表可访问才能执行有用的工作。mnesia:wait_for_tables/2 要么挂起直到 TabList 中的所有表都可访问,要么直到达到 timeout

-spec wread(TabKey :: {Tab :: table(), Key :: _}) -> [tuple()].

等效于 read(Tab, Key, write)

-spec write(Record :: tuple()) -> ok.

将记录写入数据库。

调用函数 mnesia:write(Tab, Record, write),其中 Tabelement(1, Record)

链接到此函数

write(Tab, Record, LockKind)

查看源代码
-spec write(Tab :: table(), Record :: tuple(), LockKind :: write_locks()) -> ok.

Record 写入表 Tab

该函数返回 ok,如果发生错误则终止。例如,如果不存在 person 表,则事务终止。

此函数的语义与上下文相关。有关详细信息,请参阅 mnesia:activity/4。在事务上下文中,它获取类型为 LockKind 的锁。支持锁类型 writesticky_write

-spec write_lock_table(Tab :: table()) -> ok.

等效于 lock({table, Tab}, write)