ERLANG学习 Day17

文章介绍了Mnesia数据库的事务管理,使用悲观锁定策略,演示了事务中的数据操作和可能的失败处理,以及事务被中止时数据的回滚。
摘要由CSDN通过智能技术生成

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所做的更改都被撤 销了。数据库恢复到了进入事务之前的状态。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值