管理 mnesia DBMS 中的增量计数器?

2024-02-18

我意识到 mnesia 不像 MySQL 或其他 RDBMS 那样支持自动增量功能。mnesia 文档中谈到的计数器并没有得到很好的解释。例如,到目前为止,我在整个文档中发现了一个操作计数器的函数

mnesia:dirty_update_counter({Tab::atom(),Key::any()}, Val::positive_integer())

所以,这让我困扰了一段时间,因为它适用于类型记录


{TabName, Key, Integer}  
This is also unclear and possibly because no erlang book or mnesia documentation provides an example to explain it.This has forced me to implement my own counter manipulation APIs.Since i wanted to be able to access and manage my records using counters, i had to include a field called 'counter' in my records, then at the point of adding the record in the table which is intended to have counters, i do it like this:

#recordname{field1 = Val1,...,counter = auto_increment(?THIS_TABLE)}  

计数器字段的位置并不重要。 API 的实现如下:


%% @doc this function is called whenever u are writing a new record in the table
%% by giving its result to the counter field in your record.
%% @end
%%
%% @spec auto_increment(TableName::atom()) -> integer() | exit(Reason)
auto_increment(TableName)-> case lists:member(counter,table_info(TableName,attributes)) of false -> erlang:exit({counter,field,not_found,in_table,TableName}); true -> table_info(TableName,size) + 1 end.
table_info(Tab,Item)-> F = fun({X,Y}) -> mnesia:table_info(X,Y) end, mnesia:activity(transaction,F,[{Tab,Item}],mnesia_frag).

为了解释这一点,如果计数器字段不是表的属性,我会强制让尝试执行此代码的进程以某种原因退出,因此如果程序员在 try ...catch 或 case (抓住...)的身体,他们很容易看出什么地方出了问题。或者,我可以询问此代码片段是否正在事务中执行,方法是使用mnesia:is_transaction()如果这返回 true,我打电话mnesia:abort/1,如果为 false,我可以有理由退出。另外,我在 mnesia 活动函数中使用 mnesia_frag,因为无论表的碎片属性如何,此实现都将起作用。如果我使用mnesia:transaction(Fun),碎片表将变得不一致,因为此调用将仅访问初始碎片(基表)。
现在,当从带有计数器的表中删除一条记录时,我们需要重新排列表中的顺序。此操作的成本很高,因为它需要遍历整个表。因为如果删除 counter = 5 的记录,则 counter = 6 的记录必须变为 counter = 5,依此类推。计数器大于已删除计数器的所有记录都必须递减。因此,通过传递已删除的计数器值和 TableName,可以使用以下方式迭代表
mnesia:foldl/3 or mnesia:foldr/3 , the difference between these two comes in only with ordered table types
这是处理此问题的函数:



auto_decrement(Counter_deleted,TableName)->
    Attrs = table_info(TableName,attributes),
    case lists:member(counter,Attrs) of
        false -> erlang:exit({counter,field,not_found,in_table,TableName});
        true -> 
            Counter_position = position(counter,Attrs) + 1,         
            Iterator =  fun(Rec,_) when element(Counter_position,Rec) > Counter_deleted -> 
                            Count = element(Counter_position,Rec),
                            New_rec = erlang:setelement(Counter_position,Rec,Count - 1),
                            mnesia:write(TableName,New_rec,read),
                            [];
                        (_,_) -> []
                        end,
            Find = fun({Fun,Table}) -> mnesia:foldl(Fun, [],Table) end,
            mnesia:activity(transaction,Find,[{Iterator,TableName}],mnesia_frag)
    end.
  


您注意到我有代码可以帮助我从记录中动态查找计数器字段的位置。帮助我做到这一点的代码如下所示:




position(_,[]) -> -1;
position(Value,List)->
    find(lists:member(Value,List),Value,List,1).

find(false,_,_,_) -> -1;
find(true,V,[V|_],N)-> N;
find(true,V,[_|X],N)->
    find(V,X,N + 1).

find(V,[V|_],N)-> N;
find(V,[_|X],N) -> find(V,X,N + 1).

  


之所以如此,是因为该模块不能知道程序员的任何记录来帮助他使用计数器。因此,为了使用元组操作函数从记录中访问计数器的值,例如element(N::integer(),Tuple::tuple()),我必须动态计算它在记录的元组表示中的位置。


These two functions have worked for me and are still working till auto_increment
is implemented in mnesia.

For example, using qlc (query list comprehension) to query tables with dynamic constraints, consider these pieces of code below:



select(Q)->
    F = fun(QH) -> qlc:e(QH) end,
    mnesia:activity(transaction,F,[Q],mnesia_frag).

read_by_custom_validation(Validation_fun,From_table)->
    select(qlc:q([X || X <- mnesia:table(From_table),Validation_fun(X) == true])).

%% Applying the two functions....
find_records_with_counter(From_this,To_that) when 
is_integer(From_this),is_integer(To_that),To_that > From_this -> F = fun(#recordName{counter = N}) when N >= From_this,N =< To_That -> true; (_) -> false end, read_by_custom_validation(F,TableName).

在库存管理系统中,这是有效的......




([email protected] /cdn-cgi/l/email-protection)6> stock:get_items_in_range(1,4).
[#item{item_id = "D694",name = "cement",
       time_stamp = {"30/12/2010","11:29:10 am"},
       min_stock = 500,units = "bags",unit_cost = 20000,
       state = available,last_modified = undefined,
       category = "building material",counter = 1},
 #item{item_id = "131B",name = "nails",
       time_stamp = {"30/12/2010","11:29:10 am"},
       min_stock = 20000,units = "kgs",unit_cost = 1000,
       state = available,last_modified = undefined,
       category = "building material",counter = 2},
 #item{item_id = "FDD9",name = "iron sheets",
       time_stamp = {"30/12/2010","11:29:10 am"},
       min_stock = 20,units = "bars",unit_cost = 50000,
       state = available,last_modified = undefined,
       category = "building material",counter = 3},
 #item{item_id = "09D4",name = "paint",
       time_stamp = {"30/12/2010","11:29:10 am"},
       min_stock = 30000,units = "tins",unit_cost = 5000,
       state = available,last_modified = undefined,
       category = "building material",counter = 4}]
([email protected] /cdn-cgi/l/email-protection)7>
  

这对我有用。请告诉我我应该如何处理柜台。或者你可以告诉我你如何在那边处理它们。


计数器是解决您问题的最佳方案吗?我预计高度分布式的系统最好没有它们,因此它们被排除在外。

  1. 如果您想计算表中有多少元素。拥有一个单独的记录表 {counts, TableName, Count} 并在存储表的添加和删除事务中使用 dirty_update_counter 操作。
  2. 如果您想按特定顺序(例如添加顺序)检索数据,请使用所示的 OrderedBy 解决方案here http://erlanganswers.com/web/mcedemo/mnesia/OrderedBy.html.
  3. 如果您想要快速外键查找,我会考虑使用您的键类型(item_id 的二进制值可能更快)并测试您是否获得任何显着改进。

另外,我不明白为什么在删除表条目时必须更新每条记录的计数器。我不认为 MySQL 或任何其他 RDBMS 会这样做。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

管理 mnesia DBMS 中的增量计数器? 的相关文章

  • Erlang - 导入 GPG 公钥

    我正在尝试在 Erlang 中做一些与公钥相关的事情 它们要求我跟踪公钥 根据这一页 http www erlang org doc apps public key using public key html id61611 我应该能够通过
  • 在构造函数中增加唯一的 ID 号

    我正在 C 中处理一个对象 我需要该对象的每个实例都有一个唯一的 id 我的解决方案只是在类中放置一个名为 idCount 的成员变量 并在构造函数中放置 objectID idCount idCount 我认为这可以解决我的问题 但似乎
  • 您应该将应用程序属性放在 rebar erlang 应用程序中的什么位置?

    新手问题 我编写了第一个基于 rebar 的 erlang 应用程序 我想配置一些基本属性 例如服务器主机等 放置它们的最佳位置在哪里以及如何将它们加载到应用程序中 接下来的步骤是发布版本并在其中创建节点 节点在独立的 Erlang VM
  • Erlang:如何限制分配给进程的内存

    我要问的是是否可以限制分配给特定进程的内存 堆或堆栈 以便该进程不能超过它 也许类似于 process flag min heap size MinHeapSize 但针对最大堆 您可以将某种进程跟踪 gen server 放在一起 定期检
  • Erlang 更好地支持哪种数据库(SQL)?

    你建议我在 Erlang 中使用什么 MySQL 还是 Postgres 哪个数据库有更好 更成熟 更稳定 更快 的 Erlang 驱动程序 The Erlang ODBC 接口 http erlang org doc apps odbc
  • Erlang:如何将小数转换为填充零的十六进制字符串

    我想在 Erlang 中将 42 基数 10 转换为 000002A 基数 16 我在网上找到了一些提示 io format 8 0B n 42 gt 00000042 And io format 16B n 42 gt 2A 但我似乎无法
  • 如何修改erlang中的记录?

    我需要修改操作记录中的值 place 和 other place op action walk from place to other place preconds at place me on floor me other place p
  • 如何通过 SSL 从 Phoenix Web App 连接到 PostgreSQL?

    When trying to run Elixir Phoenix Web Application using PostgreSQL Database hosted 3rd party Database as a Service Azure
  • Erlang get_tcp:recv数据长度

    I user gen tcp recv Socket 0 用于数据接收 但我只能接收1次1418字节 我怎样才能收到发送的数据量 in gen tcp recv Socket 0 您正在询问内核 给我接收缓冲区中现在可用的所有数据 不过 内
  • 如何限制Erlang VM(BEAM)使用的核心数量?

    我正在具有 2 个四核 Xeon E5520 2 2GHz 24 0GB RAM 和 Erlang R15B02 启用 SMP 的节点上运行实验 我想知道是否可以限制Erlang VM使用的核心数量 以便我可以暂时禁用一些核心并逐步增加数量
  • Erlang gen_tcp 连接问题

    简单的问题 这段代码 client gt SomeHostInNet localhost to make it runnable on one machine ok Sock gen tcp connect SomeHostInNet 56
  • Erlang 中的接受器池和负载平衡?

    From http www erlang org doc man gen tcp html accept 1 http www erlang org doc man gen tcp html accept 1 值得注意的是 accept 调
  • 如何在 erlang 中安装模块?

    我是 Erlang 新手 想知道如何安装第三方模块以在我的 Web 应用程序中使用 您将这些文件放在哪里以及执行什么类型的命令 如果您希望在系统范围内安装第 3 方库 例如 Mochiweb 最好将其设置在 ERL LIBS 环境变量下 我
  • Cowboy 中的 http 处理程序和 websocket 处理程序之间的通信

    我想在 Cowboy 中创建一个 websocket 应用程序 它从另一个 Cowboy 处理程序获取数据 假设我想结合牛仔的 Echo get 示例 https github com ninenines cowboy tree maste
  • SQLite:*防止*主键值在删除所有行后重置[重复]

    这个问题在这里已经有答案了 我有一个 SQLite 表 有几列 包括一个 ID 列 它是 INTEGER PRIMARY KEY 当我插入时 该值会按预期增加 但是 当我删除所有行时 该列的值在下一次插入时恢复为 1 有没有办法让列值从删除
  • 在 Erlang 中实现图灵机

    我有一个小项目 与实现图灵机非常相似 我遇到的基本问题是保存当前配置 例如头部的位置和更多信息 对我来说特别重要的是保留头部位置以使其向前或向后移动 Erlang 解决这个问题的方法是什么 我是 Erlang 新手 但据我探索 OTP ge
  • 为什么 epmd 进程不退出?

    在我退出 erlang shell 后 epmd 进程仍然存在 这是一个错误还是一个功能 这是很正常的 EPMD 是一个主机守护进程 当人们打算使用分布式节点时 就需要它的存在 当仅在同一台机器上使用多个节点时 它也很有用
  • Erlang 中的函数链

    最好创建像 Active Record 或 Hibernate 这样的 ORM 它应该像这样处理链式查询 User User new for login stackoverflow admin for password 1984 load
  • MySQL为什么在插入时我的自动增量不是从1开始?

    为什么当我使用 jdbc 向数据库中插入数据时 我的表 auto increment 会被提升 填充完全空表的示例 狗桌 DogId DogName 3 Woofer 4 Kujo 5 Spike 所有者表 OwnerId DogID Ow
  • Erlang 中的静态类型检查

    我慢慢地爱上了 Erlang 但只有一个很大很大的问题 我非常喜欢 Standard ML 和 ocaml 等语言 它们具有强大的静态类型检查功能 有没有一种好的 干净的方法来在 erlang 中引入某种静态类型检查 我正在看 type a

随机推荐