Erlang/OTP Forums

Author Message

<  Advanced Erlang/OTP  ~  Mnesia transaction inside an mnesia transaction etc...

Ludvig
Posted: Mon Aug 07, 2006 7:45 pm Reply with quote
User Joined: 20 Jul 2006 Posts: 38 Location: London
If you have a Mnesia transaction inside another mnesia transaction and the inner transaction fails, will the the databse do a full rollover on the whole transaction or just the inner transaction?? Or what will happen??

Example:
Code:

func1(Key) ->
Fun = fun() ->
Result = mensia:read({test,key}),
func2(Result),
mnesia:write({test2,["hi","ho"]})
end,
mnesia:transaction(Fun).

func2(Result) ->
Fun = fun() ->
mnesia:write({test2,Result})
end,
mnesia:transaction(Fun).
                 
 



-------------------
Really bad intendention..
View user's profile Send private message Visit poster's website MSN Messenger ICQ Number
oscarh
Posted: Wed Aug 23, 2006 12:55 pm Reply with quote
User Joined: 20 Jul 2006 Posts: 22
If the inner transaction is aborted, only that one is affected.

Code:

-module(test).
-compile(export_all).
-record(test, {id, value}).

create_table() ->
   mnesia:create_table(test, []).

transaction() ->
   mnesia:transaction(fun() ->
      mnesia:write(#test{id = 1, value = "test 1"}),
      mnesia:write(#test{id = 2, value = "test 2"}),
      transaction_2(),
      mnesia:write(#test{id = 3, value = "test 3"})
   end
   ).

transaction_2() ->
   mnesia:transaction(fun()->
      [Record] = mnesia:read(1),
      mnesia:write(Record#test{id = 1, value = "updated test 1"}),
      mnesia:abort(testing_abort)
   end).


Code:
Eshell V5.4.9  (abort with ^G)
1> application:start(mnesia).
ok
2> test:create_table().
{atomic,ok}
3> mnesia:dirty_all_keys(test).
[]
4> test:transaction().
{atomic,ok}
5> mnesia:dirty_all_keys(test).
[1,2,3]


You could check for the result of the inner one:
Code:

-module(test).
-compile(export_all).
-record(test, {id, value}).

create_table() ->
   mnesia:create_table(test, []).

transaction() ->
   mnesia:transaction(fun() ->
      mnesia:write(#test{id = 1, value = "test 1"}),
      mnesia:write(#test{id = 2, value = "test 2"}),
      case transaction_2() of
         {atomic, _Result}  -> ok;
         {aborted, _Reason} -> mnesia:abort(inner_aborted)
      mnesia:write(#test{id = 3, value = "test 3"})
   end
   ).

transaction_2() ->
   mnesia:transaction(fun()->
      [Record] = mnesia:read(1),
      mnesia:write(Record#test{id = 1, value = "updated test 1"}),
      mnesia:abort(testing_abort)
   end).


Code:
Eshell V5.4.9  (abort with ^G)
1> application:start(mnesia).
ok
2> test:create_table().
{atomic,ok}
3> mnesia:dirty_all_keys(test).
[]
4> test:transaction().
{aborted,inner_aborted}
5> mnesia:dirty_all_keys(test).
[]
View user's profile Send private message
Ludvig
Posted: Wed Aug 23, 2006 1:05 pm Reply with quote
User Joined: 20 Jul 2006 Posts: 38 Location: London
Thanks for trying to solve my problem. But your explanation gave me a new problem. In your code:

Code:
-module(test).
-compile(export_all).
-record(test, {id, value}).

create_table() ->
   mnesia:create_table(test, []).

transaction() ->
   mnesia:transaction(fun() ->
      mnesia:write(#test{id = 1, value = "test 1"}),
      mnesia:write(#test{id = 2, value = "test 2"}),
      case transaction_2() of
         {atomic, _Result}  -> ok;
         {aborted, _Reason} -> mnesia:abort(inner_aborted)
      end,
      mnesia:write(#test{id = 3, value = "test 3"})
   end
   ).

transaction_2() ->
   mnesia:transaction(fun()->
      [Record] = mnesia:read(1),
      mnesia:write(Record#test{id = 1, value = "updated test 1"}),
      mnesia:abort(testing_abort)
   end).


I change it to this:
Code:
-module(test).
-compile(export_all).
-record(test, {id, value}).

create_table() ->
   mnesia:create_table(test, []).

transaction() ->
   mnesia:transaction(fun() ->
      mnesia:write(#test{id = 1, value = "test 1"}),
      mnesia:write(#test{id = 2, value = "test 2"}),
      case transaction_2() of
         {atomic, _Result}  -> ok;
         {aborted, _Reason} -> mnesia:abort(inner_aborted)
      end,
      mnesia:write(#test{id = 3, value = "test 3"}),
      mnesia:abort(problem_in_paradise)
   end
   ).

transaction_2() ->
   mnesia:transaction(fun()->
      [Record] = mnesia:read(1),
      mnesia:write(Record#test{id = 1, value = "updated test 1"}),
   end).


As you can see I changed so that transaction_2 dosen't abort. But instead an aborted is done after transaction_2 is finished.

How will this affect the transactions and is there any way to abort the transaction_2 after it has been finished?
View user's profile Send private message Visit poster's website MSN Messenger ICQ Number
oscarh
Posted: Wed Aug 23, 2006 1:33 pm Reply with quote
User Joined: 20 Jul 2006 Posts: 22
First of all, in the future I should try and post code that compiles.

However, the inner transaction is never really comitted before the outer one is:
Code:

-module(test).
-compile(export_all).
-record(test, {id, value}).

create_table() ->
   mnesia:create_table(test, []).

transaction() ->
   mnesia:transaction(fun() ->
      mnesia:write(#test{id = 1, value = "test 1"}),
      mnesia:write(#test{id = 2, value = "test 2"}),
      case transaction_2() of
         {atomic, _Result}  -> ok;
         {aborted, Reason} -> mnesia:abort({inner_aborted, Reason})
          end,
      mnesia:write(#test{id = 3, value = "test 3"}),
      mnesia:abort(problem_in_paradise)
   end
   ).

transaction_2() ->
   mnesia:transaction(fun()->
      [Record] = mnesia:read({test, 1}),
      mnesia:write(Record#test{value = "updated test 1"}),
      mnesia:write(#test{id = 4, value = "test 4"})
   end).

Gives:
Code:

1> application:start(mnesia).
ok
2> test:create_table().
{atomic,ok}
3> mnesia:dirty_all_keys(test).
[]
4> test:transaction().
{aborted,problem_in_paradise}
5> mnesia:dirty_all_keys(test).
[]
View user's profile Send private message
oscarh
Posted: Wed Aug 23, 2006 1:47 pm Reply with quote
User Joined: 20 Jul 2006 Posts: 22
Also found this
View user's profile Send private message
Ludvig
Posted: Fri Aug 25, 2006 8:57 am Reply with quote
User Joined: 20 Jul 2006 Posts: 38 Location: London
Thank you!

There where some really god examples. Just what I needed.
View user's profile Send private message Visit poster's website MSN Messenger ICQ Number

Display posts from previous:  

All times are GMT
Page 1 of 1
This forum is locked: you cannot post, reply to, or edit topics.

Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum