Mnesia 事务
Mnesia采用一种悲观锁定(pessimistic locking)的策略。每当Mnesia事务管理器访问一个表 时,都会根据上下文情况尝试锁定记录甚至整个表。如果它发现这可能导致死锁,就会立即中止 事务并撤销之前所做的改动。 如果因为其他进程正在访问数据而导致事务一开始就失败了,系统就会进行短时间的等待, 然后再次尝试执行事务。这么做的一种结果就是事务fun里的代码可能会被执行很多次。事务fun里的代码不应该做任何带有副作用的事情。
中止事务
-module(test_mnesia).
-import(lists, [foreach/2]).
-compile(export_all).
-include_lib("stdlib/include/qlc.hrl").
-record(shop, {item, quantity, cost}).
-record(cost, {name, price}).
-record(design, {id, plan}).
do_this_once() ->
mnesia:create_schema([node()]),
mnesia:start(),
mnesia:create_table(shop, [{attributes, record_info(fields, shop)}]),
mnesia:create_table(cost, [{attributes, record_info(fields, cost)}]),
mnesia:create_table(design, [{attributes, record_info(fields, design)}]),
mnesia:stop().
start() ->
mnesia:start(),
mnesia:wait_for_tables([shop,cost,design], 20000).
demo(select_shop) ->
do(qlc:q([X || X <- mnesia:table(shop)]));
do(Q) ->
F = fun() -> qlc:e(Q) end,
{atomic, Val} = mnesia:transaction(F),
Val.
farmer(Nwant) ->
F = fun() ->
[Apple] = mnesia:read({shop,apple}),
Napples = Apple#shop.quantity,
Apple1 = Apple#shop{quantity = Napples + 2*Nwant},
mnesia:write(Apple1),
[Orange] = mnesia:read({shop,orange}),
NOranges = Orange#shop.quantity,
if
NOranges >= Nwant ->
N1 = NOranges - Nwant,
Orange1 = Orange#shop{quantity=N1},
mnesia:write(Orange1);
true ->
mnesia:abort(oranges)
end
end,
mnesia:transaction(F).
demo(select_shop) ->
do(qlc:q([X || X <- mnesia:table(shop)]));
do(Q) ->
F = fun() -> qlc:e(Q) end,
{atomic, Val} = mnesia:transaction(F),
Val.
在这段代码中qlc:q调用,它会把查询编译成一种用于查询数据库的内部格式。把编译后的查询传递给一个名为do()的函数,负责运行查询并返回结果。
Mnesia 启动,
查看当前商店数据。
farmer(Nwant) ->
F = fun() ->
[Apple] = mnesia:read({shop,apple}),
Napples = Apple#shop.quantity,
Apple1 = Apple#shop{quantity = Napples + 2*Nwant},
mnesia:write(Apple1),
[Orange] = mnesia:read({shop,orange}),
NOranges = Orange#shop.quantity,
if
NOranges >= Nwant ->
N1 = NOranges - Nwant,
Orange1 = Orange#shop{quantity=N1},
mnesia:write(Orange1);
true ->
mnesia:abort(oranges)
end
end,
mnesia:transaction(F).
在这段代码中在我检查橙子的数量之前更新了数据库里的苹果数量。如果事务失败它就会被撤销,数据就不会发生更改。
购买苹果后,数据发生变化。
当数量不够时,事务撤销,数据并未更改。
当这个事务失败时,mnesia:write所做的更改都被撤 销了。数据库恢复到了进入事务之前的状态。