erlang作为一门面向大规模并发、分布式的语言,起自带的mensia数据库自然应该也支持并发和分布式。不过在弄这些之前,必须了解mnesia的一些trap,可能这些在官方给出的文档中没有明确指出来:
trap1:一定要mnesia:create_schema(NodeList)吗?create_schema的功能是建立一个初始化一个模式(如果NodeList中某一个节点已经有模式,则该函数会失败)。初始化模式的操作会建立一个mnesia数据库的文件夹(如果没有),文件夹下会有一个FALLBACK.BUP文件,估计是check point之类的数据恢复文件;当mnesia:start()后,还会在该文件夹下建立一个schema.DAT文件,很显然这是模式表schema的定义文件(因为schema表是disc_copies)的,当我们建立一个ram_copies类型表的时候是不会有.DAT文件的。综上所述,如果只是把mensia当做一个内存数据库使用,根本就不用create_schema(当然,如果没有create_schema又要创建一个disc_copies的表是会报错的)。
trap2:两个节点之间一定要先ping通或者连接上才能做mnesia的分布式功能吗?不一定,erlang里面有些情况下节点之间是会自动连接的,可以我之前的文章:http://user.qzone.qq.com/876336019/2。同样,在mnesia做分布式功能时,会自动连接远程节点(当然,cookie什么的搞定先),例如move_table_copy。其实理解起来应该很简单,节点之间数据传递时,erlang会启动底层连接方法做数据传递,move_table_copy之类的操作和发送消息之类的(如:rpc:call)都是要传递数据,所以自动连接都是一样一样的。
trap3:表分片可以减少加载时间吗?总所周知,mnesia:start()虽然启动了mnesia,但是并不表示所有操作已经做完(mnesia:start()返回值是很快速的),相反,很多操作是mnesia:start()之后开始。start之后,加载硬盘中的数据到内存,同时mnesia还要判断是用本地硬盘中的数据还是其他节点上的数据。在大部分情况下,数据库加载数据是一个很耗时的工作,除非你根本没多少,为了保证一些表加载完之后再执行程序,需要做mnesia:wait_for_tables(TabList, Timeout),这个时候,整个进程被挂起,直到TabList中的每个表加载完毕。另一方面,表分片是是将一个表分为若干个更容易处理的片断,每个片断都作为第一类Mnesia表来实现,就像其它表一样,可以被复制、加索引等等,但不能是local_content表和激活snmp连接。所以,如果mnesia加载操作是单进程顺序加载,那分片不能节省时间,如果mneisa加载是多进程同时加载,那分片能节省时间。官方给出的是这样:当多个表被加载时,Mnesia按照默认的加载顺序加载。不过,可用函数
mnesia:change_table_load_order(Tab, LoadOrder)显式改变表的load_order属性来影响加载顺序。所有的表默认的LoadOrder为0,但可被设置为任何整数。有最高load_order的表将首先被加载。对需要确保重要的表能及时使用的应用程序来说,改变加载顺序非常有用。大量次要的表应设置低的加载顺序,或许低于0。根据官方关于加载策略的描述,加载是顺序进行的,所以分片不能减少加载时间(还没有试验过,下次补上试验)。