[erlang-questions] mnesia transaction

Gleb Peregud gleber.p@REDACTED
Mon Aug 3 23:20:28 CEST 2009


2009/8/3 paweł kamiński <kamiseq@REDACTED>:
> hej all,
> I tired to look for answers but all I got was about quering itslef and only
> highlighted that quering without transaction is very dangerous... :) (yeah
> tell me more)
>
> I have a question why my query in qlc cant be run without transaction??
>
> Q = qlc:q([C#client_map.rel_clientID || C <- mnesia:table(client_map),
>                        C#client_map.mtr_clientID == ClientID]),
>    Read = fun()->
>           qlc:e(Q)
>       end,
>    {atomic, List} = mnesia:transaction(Read),
>    List.
>
> my first attempt was
> Q = qlc:q([C#client_map.rel_clientID || C <- mnesia:table(client_map),
>                        C#client_map.mtr_clientID == ClientID]),
>           qlc:e(Q).

Probably qlc query could be run without transactions if you use
mnesia:activity/* with context async_dirty or sync_dirty or you could
use mnesia:async_dirty/1 or mnesia:sync_dirty/1, which, in fact, is
the same. I have never tried it, but it should work.
Please try this code:

 Q = qlc:q([C#client_map.rel_clientID || C <- mnesia:table(client_map),
                        C#client_map.mtr_clientID == ClientID]),
 mnesia:async_dirty(fun() -> qlc:e(Q) end).

> more questions :
> 1)can I select rows dirtily??

See mnesia:dirty_match_object/1 or preferably
mnesia:dirty_index_match_object/2,3. These should be optimal choice
for your use case.

mnesia:add_table_index(client_map, [rel_clientID]).
mnesia:dirty_index_match_object(#client_map{rel_clientID = Id, _ =
'_'}, rel_clientID).

Please note, according to the manual:

"The two index search functions described here are automatically
invoked when searching tables with qlc list comprehensions and also
when using the low level mnesia:[dirty_]match_object functions"

So you can use qlc in dirty context.

If you need more control you can try using mnesia:dirty_select/2.

> 2)is there a way to read snapshot of data while other processes are still
> writing to db, so transaction is no needed. I ve read in man that ther is
> fun activate_checkpoint/1 but can I run a query without transaction that
> will implicitly create such a checkpoint.??

Afaik transactions is the only way to archive this. I've tried the following:

node@REDACTED and othernode@REDACTED shares table "simple".
(node@REDACTED)> mnesia:activate_checkpoint([{name, test}, {max, [simple]}]).
(othernode@REDACTED)> mnesia:dirty_write(simple, {simple, a, 1}).
(node@REDACTED)> mnesia:dirty_all_keys(simple).
[a]
(node@REDACTED)> mnesia:dirty_read(simple, a).
[{simple,a,1}]

So checkpoints does not work for dirty operations. Please correct me
if my experiment is flawed.

> 3)then what is the difference between qlc and dirty_read, dirty_select or
> qlc is somehow compiled to dirty_* functions??

afaik, qlc is a query language, which is "compiled" down to the
appropriate functions [dirty_]read, [dirty_]select, etc. according to
the context. So your first code snippet is the same as running
mnesia:match_object in mnesia:transaction. My code for qlc in
async_dirty context is probably the same as running
mnesia:dirty_match_object.

> 4)what will exactly happened when I dirty_write to my table when 10 other
> processes are reading from it???

afaik other processes not using transactions will read or not written
changes - it depends on the timing and it is a source of race
conditions. If other processes use transactions they should be reading
consistent snapshot of data as it was before running dirty_write.
Please correct me if I'm wrong :)

>
> thanks
>
> pozdrawiam
> Paweł Kamiński

Również pozdrawiam,
Gleb Peregud


More information about the erlang-questions mailing list