非常教程

Erlang 20参考手册

mnesia

7. Mnesia系统信息 | 7. Mnesia System Information

其中包括以下专题:

  • 数据库配置数据
  • 核心转储
  • 倾倒表格
  • 检查点
  • 启动文件,日志文件和数据文件
  • 在启动时加载表
  • 从通信失败中恢复
  • 交易恢复
  • 备份,恢复,回退和错误恢复

7.1 数据库配置数据

以下两个函数可用于检索系统信息。有关详细信息,请参阅参考手册。

  • mnesia:table_info(Tab, Key) -> Info | exit({aborted,Reason}) 返回关于一个表的信息,例如表的当前大小以及它所在的节点。
  • mnesia:system_info(Key) -> Info | exit({aborted, Reason})返回有关Mnesia系统的信息,例如事务统计信息db_nodes和配置参数。

7.2堆芯堆

如果Mnesia发生故障,则将系统信息转储到MnesiaCore.Node文件中。 此文件中包含的系统信息类型也可以使用函数mnesia_lib:coredump()生成。 如果Mnesia系统行为异常,建议在错误报告中包含Mnesia核心转储文件。

7.3 倾倒表格

ram_copies类型的表按照定义存储在内存中。 但是,这些表格可以定期或在系统关闭之前转储到光盘。 函数mnesia:dump_tables(TabList)将一组RAM表的所有副本转储到光盘。 转盘时可以访问这些表格。 要将表转储为光盘,所有副本必须具有存储类型ram_copies。

表格内容放置在光盘上的.DCD文件中。 当Mnesia系统启动时,RAM表格最初加载了来自其.DCD文件的数据。

7.4 检查点

检查点是跨越一个或多个表的事务一致性状态。 当激活检查点时,系统会记住该组表格的当前内容。 检查点保持表的事务一致状态,允许在检查点处于活动状态时读取和更新表。 检查点通常用于将表备份到外部介质,但它们也在Mnesia的内部用于其他目的。 每个检查点都是独立的,并且可以同时在几个检查点中包含一个表。

每张表格都保留在检查点保留区中的旧内容。对于性能至关重要的应用程序,重要的是要实现与检查点相关的处理开销。在最坏的情况下,检查点保持器消耗比表本身更多的内存。此外,每个更新在检查点保留器附加到表的节点上变得稍慢。

对于每个表,都可以选择是否有一个检查点保留器连接到表的所有副本,或者是否只有一个检查点保留器连接到单个副本。使用每个表的单个检查点保留器,检查点消耗的内存更少,但易受节点崩溃的影响。使用多个冗余的检查点保持器,只要每个表至少有一个活动的检查点保持器,则检查点就会存活。

使用函数mnesia:deactivate_checkpoint(Name)可以明确地禁用检查点,其中Name是活动检查点的名称。 如果成功,此函数返回OK;如果有错误,则返回{error,Reason}。 检查点中的所有表必须至少附加一个检查点保留器。 当任何桌子缺少检查点保持器时,Mnesia会自动停用检查点。 当节点发生故障或复制副本被删除时,可能会发生这种情况。 使用参数min和max(在下面的列表中描述)来控制检查点保持器冗余的程度。

使用函数激活检查点mnesia:activate_checkpoint(Args),其中Args是以下元组列表:

  • {name,Name},其中Name指定检查点的临时名称。当检查点被停用时,名称可以重新使用。如果未指定名称,则会自动生成名称。
  • {max,MaxTabs},其中MaxTabs是要包含在检查点中的表的列表。默认是[](空列表)。对于这些表格,冗余是最大化的。当主表由应用程序更新时,表中的旧内容保留在检查点保留器中。如果表具有多个副本,则检查点更具容错性。当模式操作函数添加新副本时,mnesia:add_table_copy/3还会附加一个本地检查点保留器。
  • {min,MinTabs},其中MinTabs是要包含在检查点中的表的列表。默认是[]。对于这些表格,冗余最小化,并且每个表格最好在本地节点上存在单个检查点保持器。
  • {allow_remote,Bool},其中false表示所有检查点保留器必须是本地的。 如果表格不在本地,则无法激活检查点。 true允许在任何节点上分配检查点保留器。 默认值是true。
  • {ram_overrides_dump,布尔}。 该参数仅适用于ram_copies类型的表。 Bool指定RAM中的表状态是否覆盖光盘上的表状态。 true表示RAM中的最新提交记录包含在检查点保留器中。 这些是应用程序访问的记录。 false表示光盘.DAT文件中的记录包含在检查点保留器中。 这些记录在启动时加载。 默认为false。

功能mnesia:activate_checkpoint(Args)返回下列值之一:

  • {ok, Name, Nodes}
  • {error, Reason}

Name是检查点名称。Nodes是检查点已知的节点。

可以获得具有下列功能的活动检查点列表:

  • mnesia:system_info(checkpoints) 返回当前节点上的所有活动检查点。
  • mnesia:table_info(Tab, checkpoints)返回特定表上的活动检查点。

7.5 启动文件,日志文件和数据文件

本节介绍由Mnesia系统创建和维护的内部文件。特别是Mnesia描述了日志的工作原理。

启动文件

Start Mnesia声明以下开始的先决条件Mnesia

  • Erlang会话必须启动并且Mnesia必须为数据库指定一个目录。
  • 必须使用以下函数启动数据库架构mnesia:create_schema/1...

下面的示例演示如何执行这些任务:

步骤1:启动Erlang会话并指定Mnesia数据库目录:

% erl -sname klacke -mnesia dir '"/ldisc/scratch/klacke"'
Erlang (BEAM) emulator version 4.9
 
Eshell V4.9  (abort with ^G)
(klacke@gin)1> mnesia:create_schema([node()]).
ok
(klacke@gin)2> 
^Z
Suspended

步骤2:您可以检查Mnesia目录来查看创建了哪些文件:

% ls -l /ldisc/scratch/klacke
-rw-rw-r--   1 klacke   staff       247 Aug 12 15:06 FALLBACK.BUP

响应显示文件FALLBACK.BUP已经被创造了。这称为备份文件,它包含一个初始模式。如果函数中有多个节点mnesia:create_schema/1指定后,将在所有节点上创建相同的备份文件。

步骤3:启动Mnesia*

(klacke@gin)3>mnesia:start( ).
ok

步骤4:您可以在Mnesia目录中看到以下列表:

-rw-rw-r--   1 klacke   staff         86 May 26 19:03 LATEST.LOG
-rw-rw-r--   1 klacke   staff      34507 May 26 19:03 schema.DAT

备份文件中的模式FALLBACK.BUP已被用于生成文件schema.DAT。由于没有其他磁盘常驻表比架构,没有其他数据文件被创建。该文件FALLBACK.BUP在成功“恢复”后被删除。您还会看到一些供内部使用的文件Mnesia

步骤5:创建一个表:

(klacke@gin)4> mnesia:create_table(foo,[{disc_copies, [node()]}]).
{atomic,ok}

第6步:您可以在Mnesia目录中看到以下列表:

% ls -l /ldisc/scratch/klacke
-rw-rw-r-- 1 klacke staff    86 May 26 19:07 LATEST.LOG
-rw-rw-r-- 1 klacke staff    94 May 26 19:07 foo.DCD
-rw-rw-r-- 1 klacke staff  6679 May 26 19:07 schema.DAT

该文件foo.DCD已创建。该文件最终将存储写入foo表中的所有数据。

日志文件

启动Mnesia时,会创建一个名为LATEST.LOG的.LOG文件并放置在数据库目录中。 这个文件被Mnesia用来记录基于光盘的交易。 这包括在存储类型为disc_copies或disc_only_copies的表中至少写入一条记录的所有事务。 该文件还包括操纵模式本身的所有操作,例如创建新表格。 日志格式可以随着Mnesia的不同实现而变化。 Mnesia日志目前在Kernel的标准库模块disk_log中实现。

日志文件不断增长,并且必须定期进行转储。 “转储日志文件”意味着Mnesia执行日志中列出的所有操作,并将记录放入相应的.DAT,.DCD和.DCL数据文件中。 例如,如果在日志中列出操作“写入记录{foo,4,elvis,6}”,Mnesia会将操作插入到文件foo.DCL中。 之后,当Mnesia认为.DCL文件太大时,数据将被移至.DCD文件。 如果日志很大,转储操作可能很耗时。 请注意,Mnesia系统在日志转储期间继续运行。

默认情况下,Mnesia会在日志中写入100条记录或三分钟过去时转储日志。 这由两个应用程序参数-mnesia dump_log_write_threshold WriteOperations和-mnesia dump_log_time_threshold MilliSecs控制。

在转储日志之前,将文件LATEST.LOG重命名为PREVIOUS.LOG,并创建一个新的LATEST.LOG文件。 一旦成功转储日志,文件PREVIOUS.LOG将被删除。

日志在启动时以及执行模式操作时也会被转储。

数据文件

目录列表还包含一个.DAT文件,其中包含模式本身,包含在schema.DAT文件中。 DAT文件是索引文件,使用特定键在这些文件中插入和搜索记录是有效的。 .DAT文件用于架构和disc_only_copies表。 Mnesia数据文件目前在标准库模块中通过STDLIB实现。

所有可以在dets文件上执行的操作也可以在Mnesia数据文件上执行。 例如,dets包含函数dets:traverse / 2,它可以用来查看Mnesia DAT文件的内容。 但是,这只能在Mnesia没有运行时才能完成。 因此,要查看模式文件,请执行以下操作;

{ok, N} = dets:open_file(schema, [{file, "./schema.DAT"},{repair,false}, 
{keypos, 2}]),
F = fun(X) -> io:format("~p~n", [X]), continue end,
dets:traverse(N, F),
dets:close(N).

警告

必须始终使用{repair,false}选项打开DAT文件。 这确保这些文件不会自动修复。 没有这个选项,数据库可能会变得不一致,因为Mnesia可以相信这些文件已经被正确关闭了。 有关配置参数auto_repair的信息,请参阅参考手册。

警告

建议数据文件在Mnesia运行时不被篡改。虽然不被禁止,但其行为Mnesia是不可预测的。

disc_copies表使用.DCL和.DCD文件存储在磁盘上,这些文件是标准的disk_log文件。

7.6 启动时加载表格

在启动时,Mnesia加载表格以使其应用程序可以访问它们。 有时Mnesia会决定加载本地驻留的所有表,有时在Mnesia从另一个节点获取表的副本之前,这些表是不可访问的。

为了理解Mnesia在启动时的行为,了解Mnesia如何在与另一节点上的Mnesia失去联系时作出反应是非常重要的。 在这个阶段,Mnesia无法区分通信故障和“正常”节点故障。 发生这种情况时,Mnesia会假定其他节点不再运行,但实际上,节点之间的通信失败。

要克服这种情况,请尝试重新启动正在访问发生故障的节点上的表的正在进行的事务,并将mnesia_down条目写入日志文件。

在启动时,注意驻留在没有mnesia_down条目的节点上的所有表可以具有更新的副本。 他们的副本可以在当前节点上Mnesia终止后更新。 为了赶上最新的更新,从这些其他“新鲜”节点中转移表格的副本。 如果您不幸运,其他节点可能会关闭,并且您必须等待将表加载到其中一个节点上,然后才能收到表的新副本。

在应用程序第一次访问表之前,要执行mnesia:wait_for_tables(TabList,Timeout)以确保表可以从本地节点访问。 如果函数超时,应用程序可以选择使用mnesia:force_load_table(Tab)强制加载本地副本,并故意丢失本地节点关闭期间可能在其他节点上执行的所有更新。 如果Mnesia已经将表加载到另一个节点上,或者打算这样做,请从该节点复制表以避免不必要的不一致。

警告

只有一个表由mnesia:force_load_table(Tab)加载。 由于提交的事务可能导致多个表中的更新,因此强制加载可能导致表不一致。

表的允许访问模式可以定义为read_only或read_write。 它可以在运行时使用函数mnesia:change_table_access_mode(Tab,AccessMode)进行切换。 read_only表和local_content表总是在本地加载,因为不需要从其他节点复制表。 其他表主要从其他节点上的活动副本远程加载,如果表已经加载,或者如果运行的Mnesia已决定在那里加载表。

启动时,Mnesia假设其本地副本是最新版本,并在检测到以下任一情况时从光盘加载表:

  • mnesia_down从持有该表的磁盘驻留副本的所有其他节点返回。
  • 所有副本都是ram_copies

这通常是一个明智的决定,但是如果由于通信故障导致节点断开连接,这可能是灾难性的,因为Mnesia正常的表加载机制不能解决通信故障。

Mnesia负载很多表,则使用默认加载顺序。但是,可以通过显式更改load_order表的属性来影响加载顺序,并使用该函数mnesia:change_table_load_order(Tab, LoadOrder)LoadOrder0所有表的默认值,但可以设置为任何整数。最高的表load_order首先被加载。更改加载顺序对于需要确保基本表的早期可用性的应用程序特别有用。较大的外围表应具有较低的加载顺序值,可能小于0

7.7通信故障恢复

有几种情况Mnesia可以检测到网络因通信故障而被分区,例如:

  • Mnesia已经开始运作,Erlang节点再次获得联系。 然后Mnesia试图联系另一个节点上的Mnesia,看看它是否也认为网络已经被分割了一段时间。 如果两个节点上的Mnesia已经记录了mnesia_down条目,Mnesia会生成一个称为{inconsistent_database,running_partitioned_network,Node}的系统事件,并将其发送给Mnesia事件处理程序和其他可能的订阅者。 默认事件处理程序向错误记录器报告错误。
  • 如果Mnesia在启动时检测到本地节点和另一个节点彼此接收到mnesia_down,则Mnesia会生成{inconsistent_database,starting_partitioned_network,Node}系统事件,并按前一项中的描述进行操作。

如果应用程序检测到可能导致数据库不一致的通信故障,则可以使用mnesia:set_master_nodes(Tab,Nodes)函数查明哪些节点可以加载每个表。

启动时,忽略Mnesia正常表加载算法,并且从为该表定义的主节点之一加载表,而不考虑日志中潜在的mnesia_down条目。 节点只能包含表中有副本的节点。 如果节点为空,则会重置特定表的主节点恢复机制,并在下次重新启动时使用正常加载机制。

函数mnesia:set_master_nodes(Nodes)为所有表设置主节点。 对于每个表,它确定其副本节点,并使用Nodes列表中包含的副本节点(即TabNodes是节点和表的副本节点的交集)启动mnesia:set_master_nodes(Tab,TabNodes)。 如果交集为空,则重置特定表的主节点恢复机制,并在下次重启时使用正常加载机制。

函数mnesia:system_info(master_node_tables)和mnesia:table_info(Tab,master_nodes)可用于获取有关潜在主节点的信息。

确定通信失败后要保留的数据超出了Mnesia的范围。 一种方法是确定哪个“island”包含大部分节点。 对关键表使用选项{majority,true}可以确保不属于“majority island”的节点不能更新这些表。 请注意,这构成少数节点服务的减少。 这将是一个有利于更高一致性保证的折衷。

功能mnesia:force_load_table(Tab)可以用于强制加载表,而不管激活的是哪种表加载机制。

7.8 收回交易

Mnesia表可以驻留在一个或多个节点上。 当表更新时,Mnesia确保将更新复制到表所在的所有节点。 如果副本不可访问(例如,由于临时节点关闭),Mnesia稍后执行复制。

在应用程序启动的节点上,有一个事务协调器进程。如果事务是分布式的,那么在需要执行提交工作的所有其他节点上也有一个事务参与者进程。

内部Mnesia使用多个提交协议。所选协议取决于事务中哪个表已被更新。如果所有的相关表被对称地复制(即,它们都具有相同的ram_nodesdisc_nodesdisc_only_nodes当前从协调器节点可访问的),协议用于轻质事务提交。

事务协调器及其参与者需要交换的消息数量很少,因为Mnesia如果提交协议中断,表加载机制负责处理事务恢复。由于所有涉及的表都是对称复制的,因此在启动失败节点时通过从相同节点加载涉及的表来自动恢复事务。只要ACID属性可以得到保证,交易是否被提交或终止并不重要。轻量级提交协议是非阻塞的,也就是说,幸存的参与者及其协调者完成交易,即使在提交协议中间任何节点崩溃。

如果某个节点在脏操作过程中关闭,则表加载机制可确保在所有副本上执行更新,否则无。异步脏更新和同步脏更新都使用与轻量级事务相同的恢复原则。

如果事务涉及非对称复制表的更新或模式表的更新,则使用重量级提交协议。无论表如何被复制,该协议都可以完成事务。重量级事务的典型用途是将副本从一个节点移动到另一个节点。然后确保副本要么完全移动,要么保持原样。永远不要在两个节点上都有副本的情况下,或者根本没有节点。即使在提交协议的中间节点崩溃,也必须保证事务处于原子状态。重量级提交协议涉及的事务协调器和其参与者之间的消息比轻量级协议更多,并且它在启动时执行恢复工作以完成终止或提交工作。

重量级提交协议也是非阻塞的,这允许幸存的参与者和他们的协调者完成交易,无论(即使在提交协议中间节点崩溃)。当一个节点在启动时失败,Mnesia确定事务的结果并恢复它。轻量级协议,重量级协议和脏更新依赖于其他节点的操作,以做出正确的重量级事务恢复决策。

如果Mnesia尚未在事务中涉及的某些节点上启动,并且本地节点和任何已在运行的节点都不知道事务结果,则Mnesia默认情况下会等待一个事务。在最坏的情况下,所有其他涉及的节点必须先启动才能Mnesia对事务做出正确的决定并完成启动。

因此,Mnesia如果发生双重故障(在一个节点上),则可能挂起,也就是说,当两个节点同时崩溃,并且一个尝试在另一个节点拒绝启动时启动,例如由于硬件错误。

Mnesia可以指定等待其他节点响应事务恢复决定的最长时间。配置参数max_wait_for_decision默认为infinity,如前所述,这会导致无限期悬挂。但是,如果该参数设置为特定时间段(例如三分钟),Mnesia则会强制执行事务恢复决策(如果需要),以允许Mnesia继续其启动过程。

强制执行的事务恢复决策的缺点是,由于没有足够的关于其他节点的恢复决定的信息,决策可能不正确。这可能会导致数据库不一致,这些数据库Mnesia在某些节点上提交了事务,但在其他节点上终止了该事务。

在幸运的情况下,不一致仅在属于特定应用程序的表中可见。但是,如果由于执行事务恢复决定而导致模式事务不一致地恢复,则不一致的影响可能是致命的。但是,如果更高的优先级是可用性而不是一致性,则可能值得冒险。

如果Mnesia检测到不一致的事务决策,{inconsistent_database, bad_decision, Node}则会生成系统事件以使应用程序有机会安装回退或其他适当措施来解决不一致问题。Mnesia事件处理程序的默认行为与由于分区网络导致数据库变得不一致(如前所述)相同。

7.9 备份,恢复,回退和错误恢复

以下功能用于备份数据,安装备份作为回退以及错误恢复:

  • mnesia:backup_checkpoint(Name, Opaque, [Mod]) 执行包含在检查点中的表的备份。
  • mnesia:backup(Opaque, [Mod])激活覆盖所有Mnesia表的新检查点并执行备份。它以最大程度的冗余度执行(另见函数mnesia:activate_checkpoint(Args){max, MaxTabs} and {min, MinTabs})
  • mnesia:traverse_backup(Source, [SourceMod,] Target, [TargetMod,] Fun, Acc) 可用于读取现有备份,从现有备份创建备份,或将备份从一种类型的介质复制到另一种介质。
  • mnesia:uninstall_fallback()移除以前安装的后备文件。
  • mnesia:restore(Opaque, Args)从以前的备份中还原一组表。
  • mnesia:install_fallback(Opaque, [Mod])可以配置为Mnesia从现有备份重新启动和重新载入数据表以及可能的架构表。当数据或模式表损坏时,此功能通常用于灾难恢复目的。

以下各节将对这些功能进行解释。另见Checkpoints,它描述了用于激活和停用检查点的两个函数。

备份

执行备份操作的功能如下:

  • mnesia:backup_checkpoint(Name, Opaque, [Mod])
  • mnesia:backup(Opaque, [Mod])
  • mnesia:traverse_backup(Source, [SourceMod,] Target, [TargetMod,] Fun, Acc)

默认情况下,通过模块mnesia_backup对读取和写入进行实际的备份介质访问。 目前mnesia_backup是使用标准库模块disc_log实现的。 但是,您可以使用与mnesia_backup相同的接口编写自己的模块并配置Mnesia,以便备用模块执行对备份介质的实际访问。 因此,用户可以将备份放在Mnesia不知道的媒体上,可能在Erlang未运行的主机上。 为此,请使用配置参数-mnesia backup_module <模块>。

备份源是激活的检查点。备份功能mnesia:backup_checkpoint(Name, Opaque,[Mod])是最常用的,并返回ok{error,Reason}。它有以下论点:

  • Name是激活的检查点的名称。有关如何在包括检查点表名称的详细信息,请参阅该功能mnesia:activate_checkpoint(ArgList)Checkpoints
  • Opaque.Mnesia不解释这个参数,但它被转发到备份模块。在Mnesia默认的备份模块mnesia_backup将这个参数解释为本地文件名。
  • Mod备用备份模块的名称。

该功能mnesia:backup(Opaque [,Mod])激活一个新的检查点,该检查点涵盖所有Mnesia具有最大冗余度的表并执行备份。最大冗余意味着每个表副本都有一个检查点保留器。local_contents随着它们在当前节点上的查看,具有属性的表格被备份。

您可以迭代备份,可以将其转换为新备份,也可以只读取备份。功能mnesia:traverse_backup(Source, [SourceMod,] Target, [TargetMod,] Fun, Acc),通常会返回{ok, LastAcc},用于这两种用途。

在遍历开始之前,将打开源备份介质SourceMod:open_read(Source),并打开目标备份介质TargetMod:open_write(Target)。论点如下:

  • SourceModTargetMod是模块名。
  • Source和Target是模块SourceMod和TargetMod专门用于初始化备份媒体的不透明数据。
  • Acc是初始累加器值。
  • fun(BackupItems,Acc)应用于备份中的每个项目。 Fun必须返回一个元组{ValGoodBackupItems,NewAcc},其中ValidBackupItems是有效备份项目的列表。 NewAcc是一个新的累加器值。 使用函数TargetMod:write / 2将ValidBackupItems写入目标备份。
  • LastAcc是最后的累加器值,也就是最后一个NewAcc返回的值Fun

此外,可以在不更新目标备份的情况下执行源备份的只读遍历。如果为TargetMod==read_only则无访问目标备份。

通过设置SourceModTargetMod对于不同的模块,备份可以从一个备份媒体复制到另一个备份介质。

有效的BackupItems是以下元组:

  • {schema, Tab}指定要删除的表。
  • {schema, Tab, CreateList}指定要创建的表。有关CreateList,见mnesia:create_table/2...
  • {Tab, Key}指定要删除的记录的完整标识。
  • {Record}指定要插入的记录。它可以是Tab第一个字段的元组。注意记录名称被设置为表名,而不管record_name设置为什么。

备份数据分为两部分。第一部分包含与架构相关的信息。所有与模式相关的项都是元组,其中第一个字段等于原子模式。第二部分是记录部分。架构记录不能与其他记录混合,所有架构记录必须首先位于备份中。

模式本身是一个表,可能包含在备份中。模式表所在的每个节点都被视为a db_node

以下示例显示如何使用mnesia:traverse_backup来重命名备份文件中的db_node:

change_node_name(Mod, From, To, Source, Target) ->
    Switch =
        fun(Node) when Node == From -> To;
           (Node) when Node == To -> throw({error, already_exists});
           (Node) -> Node
        end,
    Convert =
        fun({schema, db_nodes, Nodes}, Acc) ->
                {[{schema, db_nodes, lists:map(Switch,Nodes)}], Acc};
           ({schema, version, Version}, Acc) ->
                {[{schema, version, Version}], Acc};
           ({schema, cookie, Cookie}, Acc) ->
                {[{schema, cookie, Cookie}], Acc};
           ({schema, Tab, CreateList}, Acc) ->
                Keys = [ram_copies, disc_copies, disc_only_copies],
                OptSwitch =
                    fun({Key, Val}) ->
                            case lists:member(Key, Keys) of
                                true -> {Key, lists:map(Switch, Val)};
                                false-> {Key, Val}
                            end
                    end,
                {[{schema, Tab, lists:map(OptSwitch, CreateList)}], Acc};
           (Other, Acc) ->
                {[Other], Acc}
        end,
    mnesia:traverse_backup(Source, Mod, Target, Mod, Convert, switched).

view(Source, Mod) ->
    View = fun(Item, Acc) ->
                   io:format("~p.~n",[Item]),
                   {[Item], Acc + 1}
           end,
    mnesia:traverse_backup(Source, Mod, dummy, read_only, View, 0).

恢复

可以从备份中在线恢复表,而无需重新启动Mnesia。使用该函数执行还原mnesia:restore(Opaque, Args),其中Args可以包含以下元组:

  • {module,Mod}。备份模块Mod用于访问备份介质。如果省略,则使用默认的备份模块。
  • {skip_tables, TableList},其中TableList是不能从备份中读取的表的列表。
  • {clear_tables, TableList},其中TableList是表格列表,在插入备份记录之前要清除。也就是说,在恢复表之前,表中的所有记录都将被删除。有关这些表的架构信息不会被清除或从备份中读取。
  • {keep_tables, TableList},其中TableList是表格列表,在插入备份记录之前不会清除。也就是说,备份中的记录被添加到表中的记录中。有关这些表的架构信息不会被清除或从备份中读取。
  • {recreate_tables, TableList},其中TableList是表格列表,在插入备份记录之前要重新创建表格。表格首先被删除,然后使用备份中的模式信息创建。备份中的所有节点都需要运行。
  • {default_op, Operation},这里Operation是操作之一skip_tablesclear_tableskeep_tables,或recreate_tables。默认操作指定要在备份中的表中使用哪些操作未在任何以前的列表中指定。如果省略,clear_tables则使用该操作。

参数Opaque被转发到备份模块。 如果成功,则返回{atomic,TabList};如果有错误,则返回元素{aborted,Reason}。 TabList是已还原表的列表。 在还原操作期间,还原的表将被写入锁定。 但是,无论由此导致的任何锁定冲突,应用程序都可以在还原操作期间继续执行其工作。

恢复是作为单个交易执行的。如果数据库很大,则不能总是在线恢复。旧数据库必须通过安装回退,然后重新启动来恢复。

倒退

函数mnesia:install_fallback(Opaque,[Mod])安装备份作为后备。 它使用备份模块Mod或默认备份模块访问备份介质。 如果成功,该函数返回OK,如果有错误,则返回{error,Reason}。

安装回退是分布式操作,仅在所有db_node上执行。 回退在系统下次启动时恢复数据库。 如果安装了回退的Mnesia节点检测到另一节点上的Mnesia已经死亡,则无条件终止其自身。

通常在执行系统升级时使用回退。系统通常涉及安装新的软件版本,并且Mnesia表格通常转换为新的布局。如果系统在升级过程中崩溃,则很可能需要重新安装旧应用程序,并将数据库恢复到之前的状态。如果在系统升级开始之前执行备份并将其作为回退进行安装,则可以执行此操作。

如果系统升级失败,则Mnesia必须重新启动所有db_nodes才能恢复旧数据库。在成功启动后,回退会自动卸载。mnesia:uninstall_fallback()系统升级成功后,该功能也可用于卸载回退。再次,这是一个分布式操作,可以全部db_nodes或者全部执行。回退的安装和卸载都要求Erlang可以运行db_nodes,但Mnesia运行与否都无关紧要。

错误恢复

系统可能因电源故障而变得不一致。UNIX功能fsck可能会修复文件系统,但不能保证文件内容是一致的。

如果Mnesia检测到文件没有正确关闭(可能由于电源故障),它会尝试以类似的方式修复损坏的文件。数据可能会丢失,但Mnesia即使数据不一致,也可以重新启动。配置参数-mnesia auto_repair <bool>可用于控制Mnesia启动时的行为。如果<bool>有值true,则Mnesia尝试修复文件。如果<bool>有值falseMnesia则在检测到可疑文件时不重新启动。此配置参数影响日志文件,DAT文件和默认备份媒体的修复行为。

配置参数-mnesia dump_log_update_in_place <bool>控制功能的安全级别mnesia:dump_log()默认情况下,Mnesia将事务日志直接转储到DAT文件中。如果在转储过程中发生电源故障,可能会导致随机访问的DAT文件损坏。如果参数设置为false,则Mnesia复制这些DAT文件并将转储目标定位到新的临时文件。如果转储成功,则将临时文件重命名为正常DAT后缀。采用这种策略,数据文件中不可恢复的不一致性的可能性变得更小。但是,事务日志的实际转储变得相当慢。系统设计者必须确定速度或安全性是否优先。

disc_only_copies启动时日志文件的初始转储期间,类型副本只受此参数的影响。在设计需求非常高的应用程序时,根本不应该使用disc_only_copies表格。其原因是正常操作系统文件的随机访问性质。如果某个节点由于电源故障等原因停机,这些文件可能会因为未正确关闭而损坏。DAT用于disc_only_copies每个事务的文件更新。

如果发生错误并且Mnesia数据库已损坏,则可以从备份重建。将此视为最后的手段,因为备份包含旧数据。数据有希望保持一致,但是当使用旧备份来恢复数据库时,数据肯定会丢失。

Erlang 20

Erlang 是一种通用的面向并发的编程语言,可应付大规模开发活动的程序设计语言和运行环境。

主页 https://www.erlang.org/
源码 https://github.com/erlang/otp
版本 20
发布版本 20.1