当前位置: 首页 > 工具软件 > Mnesia > 使用案例 >

Erlang之Mnesia简单入门

黄沈浪
2023-12-01

1.什么是Mnesia?

      Mnesia在我理解里面就是一种数据库,是Erlang自带的,它支持事务,这是最重要的事务就是要么做,要么全都不做,而且事务有几个重要的概念我们需要了解,因为只有我们知道事务有什么性质,才知道什么场景该用到事务,什么场景不需要。

2.事务几个重要概念

      1.原子性(Atomicity)——每个事务都是一个不可分割的单元,要么整体成功,要么整体失败。执行过程一旦出现失败,事务便会整体回滚,不会对数据库造成任何影响。


      2.一致性(Consistency)——执行多个事务时,即便实际执行时间有所交叠,最终的效果应该像是各个事务按一定的顺序顺次执行一样,整个过程中数据库的状态始终保持完整和一致,这说明了事务可以用于并发的场景。


     3.隔离性(Isolation)——每个事务都像是拥有一个自己的数据库副本一样,多个并发执行的事务不会相互干扰。在事务执行完毕之前任何人都观察不到事务的执行效果。


     4.持久性(Durability)——事务执行成功后,它产生的变更便会生效。如果表保存在磁盘上,那么无论是重启还是崩溃都不会导致信息丢失。

3.基本操作

     一个数据库无非是增删查改,本教程用于入门,所以有关并发编程,不会提及,场景是单点操作,还有安全权限等都没有,但以后会有相关更新,好了创建一个Mnesia基本可以分为以下几个步骤:

1.初始化Mnesia

   1.启动节点:

erl -mnesia -dir '"路径"' -name/-sname nodename.

  这一行代码,我们指定了mnesia创建的绝对位置,和创建进程的名字。

    2.建立数据库模式(schema);

      所谓数据库模式 (schema)就是一些描述信息,其中记录着当前数据库中存有哪些表,表的详细情况又如何。一般来说不用关注它——它只是Mnesia用于跟踪自身数据的一种手段。当然,要想在多个节点上建立分布式数据库,就必须在所有节点上存放一份该模式的副本,以便让节点了解自己所存的数据的一般结构。为了防止Mnesia或整个Erlang节点关闭重启时丢失数据库信息,模式数据必须保存在磁盘上,存放路径由节点启动命令中的 -mnesia dir "..." 选项指定。(我们也可以让单个或多个节点,甚至所有节点仅在RAM中保存包括数据库模式在内的所有数据;但目前我们需要的是保存在磁盘上的持久化数据库。)这个例子比较简单,只需要在本地节点上建立数据库模式即可:

    

mnesia:create_schema(node[]).


    3.启动Mnesia

        

mnesia:start().


2. 建立数据库表

         好了做完了前面几步,部署并启动了mnesia,我们就要对数据库创建表,有以下几个步骤。

      1.首先建立相应的record

            record里面的成员对应我们创建出来的表的列名,当我们插入数据时就直接插入一个记录变量就行了。

      2.利用mnesia:create_table(table_name, [Option])

            创建表table_name就是表名,Option指明了这张表的性质,在Option所有选项之中,最重要的一个就是 attributes ,几乎所有建表操作都会用上它。该选项用于指定表中所存记录的字段名。要是没它,Mnesia会假定记录中仅有两个字段,分别名为 key 和 val,我们还能指定表的类型,表一般有三种类型set,order_set,bag,若不知道这三种类型有什么不同,可以看我的上一篇ETS入门。代码举例:

mnesia:create_table(contributor,
	[{type, bag}, {attributes, record_info(fields, contributor)}]).

我们创建了一个名为contributor的表,是以contributor记录为结构,类型是bag。


3. 对数据做一些基本查询

     在我说CRUD之前,我要说明一下MNESIA在CRUD有分为2类,一种称为事务式的CRUD,一种称为脏操作,有什么不同呢,前者可以用于并发的场景,而且上下文必须是事务,不然很抛出exception exit: {aborted,no_transaction},拥有事务的全部特点,脏操作的速度更快,但是它不能用于并发的场景,什么时候应该用什么,要看你所需求的场景。

1.插入

   

mnesia:write(#user(id=Id,name=Name)).%事务式,要放在事务里面,不能单独
mnesia:dirty_write(#user(id=Id,name=Name)).%脏读

 

2.查找

    查找有2种方式,一种是用qlc库,一种是mnesia自带的select,select在简单还好,但是在复杂查询的时候非常难搞,所以我推荐使用qlc,这里我就介绍qlc。

%qlc库
just_a_qlc() ->
	mnesia:transaction(
		fun() ->
			Table = mnesia:table(user),%获取表
			QH = qlc:q(([U#user.id || U<- Table])),%筛选
			qlc:eval(QH)%获取相应列表
		end
		).



[{table_name,Key,Pid}] = mnesia:dirty_read(table_name,Key).%脏读,结果唯一Pid就是结果

我们可以看出分为三个步骤,先获取表,然后第二步就是筛选和要什么要返回什么结果,第三步就能直接用eval()返回{ok,List}

3.删除

mnesia:dirty_delete_object(#user(id=Id,name=Name)).
mnesia:delete_boject(#user(id=Id,name=Name)).

 

 

 类似资料: