erlang的分布式数据库mnesia是erlang分布式体系中非常重要的组件,其本身具有分布式的特性,可以在多个结点上建立数据副本,支持数据持久化,用好了mnesia,可以极大的减轻分布式架构的设计难度。
本博文带来的第一篇有关mnesia的分析,即是mnesia最常见也最重要的接口:transaction写过程。mnesia的文档上记载(http://www.erlang.org/doc/apps/mnesia/Mnesia_chap4.html#id73876),mnesia包含5种访问上下文,访问上下文没有固定的概念,就我的理解是指,mnesia的操作如read、write等维持事务ACID特性及分布式化的程度,这5种访问上下文分别为:
transaction:普通事务,数据更新满足事务的
ACID 特性,也会同步扩散到所有包含数据副本的mnesia结点,但事务提交时不要求各个副本结点的日志存储在磁盘上;
sync_transaction:完全同步事务,基本过程等同于transaction,但事务提交时各个副本结点的日志均已存储在磁盘上;
async_dirty:dirty_*操作的访问上下文,数据的更新不满足事务的
ACID 特性,更新的数据会异步的复制到其它副本结点;
sync_dirty:类似于async_dirty,但是直到数据完全复制到其它副本上,写操作才会返回;
ets:无任何事务及分布式特性,mnesia是通过ets和dets实现的,数据存储在这些表内,ets上下文指明mnesia仅更新本地ets表。
定义mnesia的表user:
mnesia:create_table(user, [{record_name, user},{attributes, [name, id]},{disc_copies, [node()]}]).
本文将就一条普通的mnesia语句mnesia:transaction(fun() -> mnesia:write({user, me, 12345}) end).进行分析,mnesia版本为4.5.1,揭示mnesia的事务原理。
mnesia.erl
transaction(Fun) ->
transaction(get(mnesia_activity_state), Fun, [], infinity, ?DEFAULT_ACCESS, async).
transaction(State, Fun, Args, Retries, Mod, Kind)
when is_function(Fun), is_list(Args), Retries == infinity, is_atom(Mod) ->
mnesia_tm:transaction(State, Fun, Args, Retries, Mod, Kind);
mnesia:transaction通过mnesia_tm:transaction实现,Mod参数为mnesia,Kind参数为async。
mnesia_tm.erl
transaction(OldTidTs, Fun, Args, Retries, Mod, Type) ->
Factor = 1,
case OldTidTs of
undefined -> % Outer
execute_outer(Mod, Fun, Args, Factor, Retries, Type);
{_, _, non_transaction} -> % Transaction inside ?sync_dirty
Res = execute_outer(Mod, Fun, Args, Factor, Retries, Type),
put(mnesia_activity_state, OldTidTs),
Res;
{OldMod, Tid, Ts} -> % Nested
execute_inner(Mod, Tid, OldMod, Ts, Fun, Args, Factor, Retries, Type);
_ -> % Bad nesting
{aborted, nested_transaction}
end.
execute_outer(Mod, Fun, Args, Factor, Retries, Type) ->
case req(start_outer) of
{error, Reason} ->
{aborted, Reason};
{new_tid, Tid, Store} ->
Ts = #tidstore{store = Store},
NewTidTs = {Mod, Tid, Ts},
put(mnesia_activity_state, NewTidTs),
execute_transaction(Fun, Args, Factor, Retries, Type)
end.
此处不分析嵌套事务的情况,可以看到mnesia_tm在执行事务时需要向mnesia的事务管理器发出启动事务的请求,该请求的处理过程在mnesia_tm:doit_loop中。
doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=Sup}=State) ->
receive
{From, start_outer} -> %% Create and associate ets_tab with Tid
case catch ?ets_new_table(mnesia_trans_store, [bag, public]) of
{'EXIT', Reason} -> %% system limit
Msg = "Cannot create an ets table for the "
"local transaction store",
reply(From, {error, {system_limit, Msg, Reason}}, State);
Etab ->
tmlink(From),
C = mnesia_recover:incr_trans_tid_serial(),
?ets_insert(Etab, {nodes, node()}),
Tid = #tid{pid = tmpid(From), counter = C},
A2 = gb_trees:insert(Tid,[Etab],Coordinators),
S2 = State#state{coordinators = A2},
reply(From, {new_tid, Tid, Etab}, S2)
end;
事务管理器接收请求后,将创建一个新的临时ets表,构建一个临时tid,并向请求者返回该tid和临时表,此后,涉及事务的任何操作都将写入该临时表,包括数据更新,锁,事务参与结点等信息。
重新回到execute_outer函数,观察其后续处理:
execute_outer(Mod, Fun, Args, Factor, Retries, Type) ->
case req(start_outer) of
{error, Reason} ->
{aborted, Reason};
{new_tid, Tid, Store} ->
Ts = #tidstore{store = Store},
NewTidTs = {Mod, Tid, Ts},
put(mnesia_activity_state, NewTidTs),
execute_transaction(Fun, Args, Factor, Retries, Type)
end.
另一个值得注意的细节在于,mnesia将{Mod, Tid, Ts(也即刚才创建的临时表)}存储在发起事务进程的进程字典内,这将在之后的mnesia:write中进行后续检查。
execute_transaction(Fun, Args, Factor, Retries, Type) ->
case catch apply_fun(Fun, Args, Type) of
{'EXIT', Reason} ->
check_exit(Fun, Args, Factor, Retries, Reason, Type);
{atomic, Value} ->
mnesia_lib:incr_counter(trans_commits),
erase(mnesia_activity_state),
flush_downs(),
catch unlink(whereis(?MODULE)),
{atomic, Value};
{nested_atomic, Value} ->
mnesia_lib:incr_counter(trans_commits),
{atomic, Value};
Value -> %% User called throw
Reason = {aborted, {throw, Value}},
return_abort(Fun, Args, Reason)
end.
apply_fun(Fun, Args, Type) ->
Result = apply(Fun, Args),
case t_commit(Type) of
do_commit ->
{atomic, Result};
do_commit_nested ->
{nested_atomic, Result};
{do_abort, {aborted, Reason}} ->
{'EXIT', {aborted, Reason}};
{do_abort, Reason} ->
{'EXIT', {aborted, Reason}}
end.
execute_transaction通过apply执行了传入mnesia:transaction的函数后,便进行了提交过程。
至此,事务准备过程已经完成,本节点的mnesia事务管理器为事务发起者分配了一个事务tid和一张临时表,并记录了相关分配信息,事务发起者也在进程字典内记录了transaction访问上下文。
未完待续...
分享到:
相关推荐
session, specify a Mnesia database directory, initialize a database schema, start Mnesia, and create tables. Initial prototyping of record definitions is also discussed. • Build a Mnesia Database ...
Mnesia 是一个分布式数据库管理系统,它是 Erlang 语言环境的一部分,专门设计用于在分布式系统中存储和查询数据。随着业务需求的增长,单个 Mnesia 表的大小和性能可能会成为瓶颈。为了解决这个问题,Mnesia 提供了...
AMNESIA是一个基于Erlang编程语言的开源库,专门设计用于简化与关系数据库管理系统(RDBMS)的交互。Erlang以其并发处理、容错性和高效性能在分布式系统领域备受推崇,而AMNESIA则进一步扩展了Erlang的功能,使...
Mnesia是Erlang OTP (Open Telephony Platform) 库中的一个核心组件,它是一个强大的分布式数据库系统,特别适用于需要高可用性、容错性和实时性能的场景,比如电信和相关领域。 Mnesia的设计理念是与Erlang的并发...
B站视频地址: 做了文字校验,已经成功上线,有兴趣的小伙伴可以扫码体验:可以微信搜索:失忆备忘录一、失忆的由来之所以开发这款软件,是因为在那段时间事情很多,但是经常忘记。虽然市面上类似的功能很多,我之前...
Api-Social-Amnesia.zip,忘记过去。社交健忘症确保你的社交媒体帐户只显示你最近的历史,而不是5年前“那个阶段”的帖子。,一个api可以被认为是多个软件设备之间通信的指导手册。例如,api可用于web应用程序之间的...
语言:English (United States) 遗忘的延伸 Chrome失忆症是一个Chrome扩展程序,可让您有选择地不记得自己的任何浏览历史记录。...有关更多信息,请访问https://github.com/DanielBok/chrome-amnesia。
8.附录.A:Mnesia.错误信息 8.1.Mnesia.中的错误 9.附录.B:备份回调函数接口 9.1.Mnesia.备份回调行为 10.附录.C:作业存取回调接口 10.1.Mnnesia.存取回调行为 11.附录.D:分片表哈希回调接口 11.1....
4. **事务处理**:Mnesia支持原子性、一致性、隔离性和持久性(ACID)事务,确保了数据操作的可靠性和一致性。 5. **模式定义**:Mnesia允许用户定义数据库模式,包括表、索引和属性等,提供了一种结构化的方式来...
Mnesia 是一个强大的分布式数据库管理系统(DBMS),专门为Erlang编程语言设计,特别适用于需要高可用性、持续运行和软实时特性的电信和其他关键业务应用。这个系统允许在多个节点间同步数据,提供了一种在分布式...
4. 分布式事务处理:Mnesia支持将事务分布在多个节点上执行,并允许在一个事务中调用大量的函数。这样可以实现高效的事务处理和功能集成。 5. 并发事务执行:Mnesia能够保证多个事务并发执行,并由数据库管理系统...
失忆症是一种提醒,允许您定义警报,贴纸(贴子)以提醒您一些重要的内容以及有关所需内容的注释。 可以将警报编程为在给定时间显示,可以在桌面上放置贴纸以随时查看。
Mnesia是一个分布式数据库管理系统(DBMS),适合于电信和其它需要持续运行和具备软实时特性的Erlang应用。 目 录 1 、介绍 . . .. . .. . . .. . 4 1.1 关于 Mnesia . . .. . .. . . .. . 4 1.2 Mnesia ...
Mnesia 作为一个专为电信应用和其他需要高可靠性、高性能以及软实时特性的Erlang应用程序设计的分布式数据库管理系统,不仅提供了强大的数据管理和处理功能,还通过其独特的分布式架构和高容错性设计,成为了构建...
"Amnesia"是一个可能与计算机安全或数据丢失相关的主题,暗示了系统或用户可能遭遇了某种形式的记忆丧失,即数据无法访问或丢失的情况。在IT领域,这种情况通常涉及到磁盘故障、病毒攻击、误操作或者软件错误。"Post...