当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


erlang transaction(Fun)用法及代码示例


transaction(Fun) -> t_result(Res)
transaction(Fun, Retries) -> t_result(Res)
transaction(Fun, Args :: [Arg :: term()]) -> t_result(Res)
transaction(Fun, Args :: [Arg :: term()], Retries) ->
 t_result(Res)
类型:
Fun = fun((...) -> Res)
Retries = integer() >= 0 | infinity

将带有参数 Args 的函数对象 Fun 作为事务执行。

事务内部执行的代码可以由一系列表操作函数组成。如果由于用户错误或某个表不可用而导致事务内部出现问题,则整个事务将终止,并且函数 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 异常。

相关用法


注:本文由纯净天空筛选整理自erlang.org大神的英文原创作品 transaction(Fun) -> t_result(Res)。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。