0

使用一些简单的 mnesia 代码,我遇到了一个不寻常的错误。这个问题是我的另一个问题的后续,但现在我有代码来重现这个问题。

我正在使用这个二郎:

Erlang R16B01 (erts-5.10.2) [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]

在 Arch Linux 上。

如果我有这个代码:

-module(test).

-export([test/0, tryread/0]).

-record(rec, { a, b }).

test() ->
    install(),

    {atomic, ok} = mnesia:transaction(fun() -> mnesia:write({rec, y, y}) end),
    {atomic, ok} = mnesia:transaction(fun() -> mnesia:write({rec, z, z}) end).

tryread() ->
    mnesia:transaction(fun() ->
                               mnesia:read(rec, y)
                       end).

install() ->
    mnesia:create_schema([node()]),

    ok = mnesia:start(),

    {atomic, ok} = mnesia:create_table(rec, [
                                             {attributes,       record_info(fields, rec)},
                                             {disc_only_copies, [node()]},
                                             {type,             set}
                                            ]).

在一个名为的文件中test.erl,我开始erl并输入以下内容:

1> c(test).
{ok,test}
2> test:test().
{atomic,ok}
3> test:tryread().
{atomic,{error,{bad_object_header,"/.../Mnesia.nonode@nohost/rec.DAT"}}}

作为旁注,如果我退出erl并重新启动它,然后执行mnesia:start(),我会收到以下警告:

dets:文件“/.../Mnesia.nonode@nohost/rec.DAT”未正确关闭,正在修复...

这对我来说是非常可靠的行为。我可以删除整个数据库,重新运行测试,得到完全相同的结果。

一件事是,如果我在两个事务之后立即将调用tryread放在函数内部,它就可以正常工作。test它是tryread从导致错误的 REPL 调用的。

如果我将我的 erlang Arch 安装包从 R16B01-1 降级到 R16B-3,我不会收到此错误。任何比此更新的版本都会出现此错误。

其他人可以重现此错误吗?是什么原因造成的?

4

1 回答 1

1

我无法在我的机器上的 R16B01 上重现它。

需要注意的一些事项:

  • 关闭 mnesia 时必须正确调用 mnesia:stop()。如果硬退出 shell,磁盘上的 DETS 表将需要修复,这可能就是您遇到的情况。
  • 您希望通过 DETS 复制有什么特别的原因disc_only_copies吗?事件disc_copies要快得多,因为它们将数据集保存在内存中以及磁盘上的磁盘日志中。对于纯粹基于磁盘的存储,根据我的经验,还有其他选项通常比 mnesia 更好。
  • 我的猜测是,由于某种原因,您最终会遇到错误的配置错误的方案。猜测可能是具有权限的东西。rec.DAT 可能已损坏,但我不知道是什么使它朝那个方向倾斜。
于 2013-06-24T13:47:53.817 回答