第五届蓝桥杯软件大赛C/C++本科B组决赛解题报告

mnesia在频繁操作数据的过程可能会报错:** WARNING ** Mnesia is overloaded: {dump_log, write_threshold},可以看出,mnesia应该是过载了。这个警告在mnesia dump操作会发生这个问题,表类型为disc_only_copies 、disc_copies都可能会发生。

如何重现这个问题,例子的场景是多个进程同时在不断地mnesia:dirty_write/2

mnesia过载分析

1、抛出警告是在mnesia 增加dump worker的时候

mnesia_controller.erl

抛出警告是当Worker的#dump_log.opt_reply_to 未定义,仔细看这里的代码,这一步先检查了dumper_queue里的worker

所以,mnesia抛出过载警告有2个条件:

1)当worker的#dump_log.opt_reply_to 未定义

2)dumper_queue有相同操作(InitBy)的worker

2、那什么样的worker的#dump_log.opt_reply_to 未定义?

代码也在mnesia_controller.erl,这里add的worker的dump_log.opt_reply_to 未定义,而{async_dump_log, InitBy} 就是 mnesia:dirty_write/2的过程中调用mnesia_controller:async_dump_log(write_threshold) 产生的。

就是说,mnesia:dirty_write/2会触发异步dump操作,而只有异步的dump会导致mnesia抛出过载警告

3、看一下,mnesia什么时候会修正worker?

代码也在mnesia_controller.erl,在dump完成时,mnesia会修改worker的dump_log.opt_reply_to,然后移出dumper_queue

从上面可以得到结论,mnesia:dirty_write/2的操作是会触发异步dump操作,每次dump操作mnesia都会加到dumper_queue队列,mnesia通过检查dumper_queue是否存有相同操作的worker来检查是否过载

mnesia dump分析

mnesia数据存储实际上使用的是ets和dets,对于ram_copies类型的表使用ets;disc_copies表也使用ets,通过dump将数据保存到*.DCD(disc copy data)文件来持久化,中间可能会用*.DCL(disc copy log)转储;而disc_only_copies表使用的是dets,保存的文件为*.DAT。

表类型不同,mnesia记录数据的过程也不同,这里先讨论mnesia 记录disc_copies数据的过程。

1、mnesia 记录disc_copies数据有2个过程:

1)操作先记录到日志文件LATEST.LOG,然后再dump到*.DCD文件,同时清除LATEST.LOG

2)把修改同步到ets表中

2、mnesia disc_copies表数据dump过程

1)将日志文件LATEST.LOG重命名为PREVIOUS.LOG,然后再新建一个空的日志文件LATEST.LOG

2)分析PREVIOUS.LOG文件中的内容,将disc_copies的表实际修改写到*.DCL文件

3)比较*.DCL和*.DCD的大小,当filesize(*.DCL) > filesize(*.DCD) / dc_dump_limit,把*.DCL的记录存储到*.DCD文件中。dc_dump_limit默认为4,可以通过-mnesia dc_dump_limit Number设置

3、mnesia什么时候会dump

1)定时触发

mnesia启动后,mnesia_controller进程设置定时器,触发dump

mnesia_controller.erl:

默认值为180000,可以通过 -mnesia dump_log_time_threshold 300000 设置。

2)一定次数的操作后触发

每次数据操作,mnesia都会调用mnesia_log:log/1或者mnesia_log:slog/1进行日志记录,记录一次日志就将trans_log_writes_left的值减1,当这个值为0时,触发dump

mnesia_log.erl:

mnesia_dumper.erl :

默认值为1000,可以通过 -mnesia dump_log_write_threshold 50000 设置。

3)手动dump

手动调用 mnesia:dump_log/0  可以强制mnesia 完成dump,而这个dump是同步的

mnesia.erl:

mnesia_controller.erl:

解决mnesia过载

结合上面的分析再谈谈mnesia过载问题,dict_copies表写数据的时候,mnesia会写记录到ets表和日志文件LATEST.LOG,然后定时或定量dump做持久化。通过dump_log_write_threshold /dump_log_time_threshold 可以控制持久化的频率。mnesia在dump数据的时候,如果上一个worker进程dump没完成,就抛出过载警告。对此,dump_log_write_threshold的值表示mnesia经历过多少数据操作做一次持久化,dump_log_time_threshold的值表示mnesia多长时间做一次持久化。

这里再谈谈,为何同一时间只能有一个dumper?

dump的过程是先将日志文件重命名为PREVIOUS.LOG,然后分析PREVIOUS.LOG的数据做持久化,如果同时有第二个dump,将会替换掉第一个dump的PREVIOUS.LOG,影响第一个dump的持久化。那么,聪明的你就会这么想,为何不重命名为XXX.LOG,每次重命名都不同?事实上,如果同时有两个dumper,mnesia仅保证第二个dump能正常进行,放弃掉第一个dump的数据。所以,mnesia出现过载警告的时候,数据有可能会丢失。

这里,我做过了一项测试,修改mnesia的代码,将所有异步dump去掉,改用定时手动dump。还是原来的例子,发现第一个dump还没完成日志文件的分析和持久化,而新的日志文件已经增长到快2G。

dump的过程在文件io层面上其实是,一边在没有控制的追加数据,一边又在分析文件和有序写入,这个过程是在挑战磁盘io的读写极限啊。所以,就算现在有多个dumper,结果只会让cpu和硬盘更加抓狂。

另外,别太过依赖dump_log_write_threshold/dump_log_time_threshold这两个参数,改大了就有用吗?

这两个参数改大了,就是说,dump的频率就会降低,那么等待dump的数据就会更多,dump花的时间将会越长,到头来还是不能解决到问题。这两个参数的意义在于平缓写入速度,避免一时间大量数据写入造成数据丢失。但是,如果每时每刻都是高密度写入,硬盘也承受不了,一般到了这个局面,问题应该从数据缓冲和持久化的设计上去解决,而不是想着换一个数据库去解决。

这里有一点经验可以分享一下:

1、在mnesia没报过载错误的时候,不建议去改动,调节这些参数会影响持久化

2、可以多个进程读mnesia的数据,但写数据的过程只交给少数几个进程去完成

参考:

http://blog.csdn.net/mycwq/article/details/28660813

http://my.oschina.net/hncscwc/blog/161763

第五届蓝桥杯软件大赛C/C++本科B组决赛解题报告,布布扣,bubuko.com

时间: 2024-10-06 08:32:59

第五届蓝桥杯软件大赛C/C++本科B组决赛解题报告的相关文章

蓝桥杯软件大赛练习系统——基础练习 十进制转十六进制

问题描述 十六进制数是在程序设计时经常要使用到的一种整数的表示方式.它有0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F共16个符号,分别表示十进制数的0至15.十六进制的计数方法是满16进1,所以十进制数16在十六进制中是10,而十进制的17在十六进制中是11,以此类推,十进制的30在十六进制中是1E. 给出一个非负整数,将它表示成十六进制的形式. 输入格式 输入包含一个非负整数a,表示要转换的数.0<=a<=2147483647 输出格式 输出这个整数的16进制表示 样例输入

算法笔记_206:第五届蓝桥杯软件类决赛真题(Java语言A组)

目录 1 海盗分金币 2 六角幻方 3 格子放鸡蛋 4 排列序数 5 幂一矩阵 6 供水设施   1 海盗分金币 有5个海盗,相约进行一次帆船比赛. 比赛中天气发生突变,他们被冲散了. 恰巧,他们都先后经过途中的一个无名的荒岛,并且每个人都信心满满,觉得自己是第一个经过该岛的人. 第一个人在沙滩上发现了一堆金币.他把金币分成5等份.发现刚好少一个金币.他就从自己口袋拿出一个金币补充进去,然后把属于自己的那份拿走. 第二个到达的人也看到了金币,他也和第一个人一样,把所有金币5等分,发现刚好缺少一个

算法笔记_111:第五届蓝桥杯软件类省赛真题(Java本科A组)试题解答

 目录 1 猜年龄 2 李白打酒 3 神奇算式 4 写日志 5 锦标赛 6 六角填数 7 绳圈 8 兰顿蚂蚁 9 斐波那契 10 波动数列   前言:以下试题解答代码部分仅供参考,若有不当之处,还请路过的同学提醒一下~ 1 猜年龄 标题:猜年龄 小明带两个妹妹参加元宵灯会.别人问她们多大了,她们调皮地说:"我们俩的年龄之积是年龄之和的6倍".小明又补充说:"她们可不是双胞胎,年龄差肯定也不超过8岁啊." 请你写出:小明的较小的妹妹的年龄. 注意: 只写一个人的年龄数

蓝桥杯软件大赛练习系统——算法训练 最小乘积(基本型)

************************************************************************ * 精品书籍推荐:<算法竞赛入门经典> * 该书对于ACMer几乎人手一本,所以在这里倾力推荐,读完这本书,我们就可以开始我们的算法征程了!!! * 看完上面那本书,还有一本它的升级版:<算法竞赛入门经典:训练指南> * 再读完这本书,你就超神了!!! *******************************************

第六届蓝桥杯软件大赛A组预赛

以下只是我的个人答案,欢迎讨论指正! 还有最后两题求正解 方程整数解 方程: a^2 + b^2 + c^2 = 1000 (或参见[图1.jpg]) 这个方程有整数解吗?有:a,b,c=6,8,30 就是一组解. 你能算出另一组合适的解吗? a,b,c=10,18,24 请填写该解中最小的数字. 10 注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字. 代码: #include <iostream> #include <cstdio> #include <c

蓝桥杯 幂一矩阵 2014年JavaB组决赛第5题

标题:幂一矩阵 天才少年的邻居 atm 最近学习了线性代数相关的理论,他对"矩阵"这个概念特别感兴趣.矩阵中有个概念叫做幂零矩阵.对于一个方阵 M ,如果存在一个正整数 k 满足 M^k = 0 ,那么 M 就是一个幂零矩阵.(^ 表示乘方) atm 不满足幂零矩阵,他自己设想了一个幂一矩阵:对于一个方阵 M ,如果存在一个正整数 k 满足 M^k = I ,其中 I 是单位矩阵,那么 M 就是一个幂一矩阵. atm 特别钟情于这样一种方阵:每行每列有且仅有一个 1 .经过 atm 不

第五届蓝桥杯全国软件设计大赛--2013年校内选拔赛Java题目

第五届蓝桥杯全国软件设计大赛 2013年校内选拔赛Java题目 一.考生注意: (1)[结果填空题]要求参赛选手根据题目描述直接填写结果.求解方式不限.不要求源代码. 把答案存入[考生文件夹]下对应题号的文件中即可. (2)[代码填空题]要求参赛选手在弄清给定代码工作原理的基础上填写缺失的部分,使得程序逻辑正确.完整.所填写的代码不超过一条语句(即中间不能出现分号). 把填空的答案(仅填空处的答案,不包括题面已存在的代码)存入[考生文件夹]下对应题号的文件中中即可. (3)[编程题]要求选手设计

第五届蓝桥杯C++本科A组

今天上午参加了第五届蓝桥杯比赛,还是去年的地方,还是去年的考场,不同的是经过了一年的历练,多了一份坦然与自信.不管最后结果如何,是对自己一年学习的一个小小的交代.ACMER IN HHUC, we never say no. 结果填空 1. a*a+b*b+c*c=1000;a,b,c均为整数,求一组解中的最小值.暴力的题目,很容易就想到了0,10,30.所以没多想就填上了0,可是考完发现还可以是负数...悲了个剧了,三分就这么水没了.. 2. 类似于往年的一道高斯的生日,求距离某一天(yyyy

算法笔记_216:第六届蓝桥杯软件类校赛部分真题(Java语言C组)

目录 1 题目一 2 题目二 3 题目三 4 题目四 5 题目五 前言:以下代码仅供参考,若有错误欢迎指正哦~ 1 题目一 二项式的系数规律,我国数学家很早就发现了. 如[图1.png],我国南宋数学家杨辉1261年所著的<详解九章算法>一书里就出现了. 其排列规律: 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 1 6 15 20 15 6 1 1 7 21 35 35 21 7 1 如下的程序,用来建立N行的杨辉三角形.请填写划线部分缺少的代码.