【发布时间】:2010-12-21 23:17:59
【问题描述】:
我在 mnesia 中有一个表,我需要更新其中记录中的各个字段。根据Erlang : Mnesia : Updating a single field value in a row,如果我这样做:
update_a(Tab, Key, Value) ->
fun() ->
[P] = mnesia:wread({Tab, Key}),
mnesia:write(Tab, P#rec{a=Value}, write)
end.
现在据我了解,上面的代码基于Key 读取记录P,获取记录上的写锁,因此在读取和写回记录时没有其他事务修改该记录(或简而言之,更新)。到目前为止一切顺利。
现在我的要求是我需要能够根据Key 和表中的另一个字段读取记录,然后对其执行更新。用于查找的函数是mnesia:match_object。现在的问题是,根据http://www.erlang.org/doc/man/mnesia.html#match_object-3,这个函数只支持读锁,不支持写锁。
这样做的结果是,假设在上面的函数中我要使用 mnesia:match_object,我将得到一个(一组)记录,所有记录都带有读锁。读取记录后,我需要对检索到的数据进行一些检查,然后仅在满足条件时才写回更新的记录。现在,假设有两个并行事务 T1 和 T2 由两个不同的源在运行。 T1 和 T2 都同时访问同一个记录。由于它们是读锁定的,因此 T1 和 T2 都可以并行读取记录。 T1 和 T2 都将对同一条记录执行相同的检查,如果条件匹配,则两者都将继续执行更新。但是,在我的代码中,如果 T1 和 T2 连续执行,T1 会对记录进行更改,而在 T2 中,它会读取这些更改的记录,并且条件会失败并且不会进行更新。
简而言之,我需要编写 mnesia:match_object 返回的锁记录。该文档明确指出仅支持读锁。有没有其他选择?
更新: 我一直在做一些试验,我认为可能的解决方案是使用复合键。假设我将数据写入如下表:
mnesia:transaction(fun() -> mnesia:write(mytable, #rec{i={1,2}, a=2, b=3}, write) end).
有没有办法使用 don't cares 来查找条目?
我尝试了这些,但都返回了空结果:
mnesia:transaction(fun()-> mnesia:read(mytable, {1,'_'}, read) end).
mnesia:transaction(fun()-> mnesia:read(mytable, {1,_}, read) end).
【问题讨论】: