热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Erlang:Mnesia:根据键以外的字段查找和更新-Erlang:Mnesia:Lookupandupdatebasedonfieldsotherthanthekey

IhaveatableinmnesiaandIneedtoupdateindividualfieldsintherecordsinit.AccordingtoE

I have a table in mnesia and I need to update individual fields in the records in it. According to Erlang : Mnesia : Updating a single field value in a row if I do something like:

我在mnesia中有一个表,我需要更新其中的记录中的各个字段。根据Erlang:Mnesia:如果我执行以下操作,则连续更新单个字段值:

update_a(Tab, Key, Value) ->
  fun() ->
    [P] = mnesia:wread({Tab, Key}),
    mnesia:write(Tab, P#rec{a=Value}, write)
  end.

Now as I understand, the above code reads a record P based on a Key, acquiring a write lock on the record, so that no other transactions modify this record while it is being read and written back (or in short, updated). So far so good.

根据我的理解,上面的代码根据Key读取记录P,获取记录上的写锁定,以便在读取和写回(或简称,更新)时,没有其他事务修改此记录。到现在为止还挺好。

Now my requirement is that I need to able to read records based on both the Key and one other field in the table and then perform an update on it. A function that will do this looking up is mnesia:match_object. The problem now is that, the function only supports a read lock, not a write lock, according to http://www.erlang.org/doc/man/mnesia.html#match_object-3.

现在我的要求是我需要能够根据表中的Key和另一个字段读取记录,然后对其执行更新。将要查找的函数是mnesia:match_object。现在的问题是,根据http://www.erlang.org/doc/man/mnesia.html#match_object-3,该函数仅支持读锁,而不支持写锁。

The consequence of this is that, suppose in the above function I were to use mnesia:match_object, I will get a (group of) record(s), all with read locks. After I read the records, I need to perform some checks on the retrieved data and then write back the updated record only if a condition is satisfied. Now, assume there are two parallel transactions T1 and T2 initiated by two different sources running. Both T1 and T2 access the same record, at the same time. Since they are read locked, both T1 and T2 will be able to read the records parallely. Both T1 and T2 will perform the same check on the same record, and if the condition matches, both will proceed to execute the update. But, in my code, if T1 and T2 were to have executed serially, T1 would have made changes to the record and in T2, it would have read these changed records and the condition would have failed and no update would have been made.

这样做的结果是,假设在上面的函数中我使用的是mnesia:match_object,我将获得一组(一组)记录,所有记录都带有读锁。在我读取记录之后,我需要对检索到的数据执行一些检查,然后仅在条件满足时写回更新的记录。现在,假设有两个并行事务T1和T2由两个不同的源运行启动。 T1和T2都同时访问相同的记录。由于它们被读锁定,因此T1和T2都能够并行读取记录。 T1和T2都将对同一记录执行相同的检查,如果条件匹配,则两者都将继续执行更新。但是,在我的代码中,如果T1和T2已经连续执行,T1将对记录进行更改,而在T2中,它将读取这些已更改的记录,并且条件将失败并且不会进行更新。

In short, I need to write lock records that are returned by mnesia:match_object. The documentation clearly states only read lock is supported. Are there are any alternatives?

简而言之,我需要编写由mnesia:match_object返回的锁记录。文档明确指出只支持读锁定。有没有其他选择?

UPDATE: I've been experimenting a little bit, and a possible solution I thought could be to use compound keys. Suppose I have data written to a table like:

更新:我已经尝试了一点,我认为可能的解决方案是使用复合键。假设我将数据写入表中,如:

mnesia:transaction(fun() -> mnesia:write(mytable, #rec{i={1,2}, a=2, b=3}, write) end).

Is there any way to lookup entries, using don't cares?

有没有办法查找条目,使用不关心?

I tried these, but both returned empty results:

我试过这些,但都返回空结果:

mnesia:transaction(fun()-> mnesia:read(mytable, {1,'_'}, read) end).
mnesia:transaction(fun()-> mnesia:read(mytable, {1,_}, read) end).

4 个解决方案

#1


1  

You don't have to worry about it. From the mnesia documentation:

你不必担心它。来自mnesia文档:

Read locks may be shared, which means that if one transaction manages to acquire a read lock on an item, other transactions may also acquire a read lock on the same item. However, if someone has a read lock no one can acquire a write lock at the same item. If some one has a write lock no one can acquire a read lock nor a write lock at the same item.

读锁可以是共享的,这意味着如果一个事务设法获取对项的读锁,则其他事务也可以获取对同一项的读锁。但是,如果有人有读锁定,则没有人可以在同一个项目上获得写锁定。如果某个人有写锁定,则没有人可以在同一个项目中获取读锁定或写锁定。

If a transaction has a read lock on an object, that object can't be edited by another transaction.

如果事务对对象具有读锁定,则该对象不能由另一个事务编辑。

Say you have two transactions, T1 and T2, which are executing in parallel:

假设您有两个并行执行的事务T1和T2:

  1. T1 does mnesia:match_object, and acquires a read lock on all the returned objects.
  2. T1执行mnesia:match_object,并获取所有返回对象的读锁定。
  3. T2 does an equivalent mnesia:match_object, and acquires a read lock on the same objects.
  4. T2执行等效的mnesia:match_object,并获取相同对象的读锁定。
  5. T2 attempts to acquire a write lock on of the objects (to edit it).
  6. T2尝试获取对象的写锁定(以编辑它)。
  7. Mnesia automatically aborts T2, to be retried later.
  8. Mnesia自动中止T2,稍后重试。
  9. T1 acquires a write lock on the objects, and edits them.
  10. T1获取对象的写锁定,并对其进行编辑。
  11. T1 finishes.
  12. T1完成。
  13. Mnesia retries T2.
  14. Mnesia重试T2。

Note that T2 may be retried several times, depending on how long T1 takes to complete (ie. release its locks).

请注意,T2可能会重试几次,具体取决于T1完成所需的时间(即释放其锁定)。

According to my tests, the locking behavior of mnesia:match_object isn't consistent. For example, mnesia:match_object(mytable, {mytable, 2, '_'}, LockType) will lock only the record with Key 2, but mnesia:match_object(mytable, {mytable, '_', test}, LockType) locks the entire table.

根据我的测试,mnesia:match_object的锁定行为不一致。例如,mnesia:match_object(mytable,{mytable,2,'_'},LockType)将仅锁定具有键2的记录,但是mnesia:match_object(mytable,{mytable,'_',test},LockType)锁定整个桌子。

Also note that the documentation isn't correct, mnesia:match_object(Table, Pattern, write) does work, and seems to follow the same pattern as 'read', ie. if you specify the key, only the matching record will be write-locked; if you don't specify the key, the entire table will be write-locked.

另请注意,文档不正确,mnesia:match_object(Table,Pattern,write)确实有效,并且似乎遵循与'read'相同的模式,即。如果指定密钥,则只有匹配的记录会被写入锁定;如果您未指定密钥,则整个表将被写入锁定。

You can test it yourself by doing something like this:

您可以通过执行以下操作来自行测试:

test() ->
    mnesia:transaction(fun()-> 
        Table = mytable,
        Matches = mnesia:match_object(Table, {Table, 2, '_'}, write),
        io:format("matched: ~p~n", [Matches]),
        spawn(fun()->mnesia:transaction(fun()->
                        io:format("trying to read~n",[]),
                        io:format("read: ~p~n", [mnesia:read(Table, 2, read)])
                        end) end),        
        timer:sleep(1000),
        RereadMatches = lists:map(fun(#mytable{id=Id}) -> mnesia:read(Table, Id, write) end, Matches),
        io:format("reread matches: ~p~n", [RereadMatches])
        end).

By changing the pattern and lock type passed to match_object, and the key number and lock type passed to mnesia:read in the spawned process (or by using mnesia:write), you can test the various locking behaviors.

通过更改传递给match_object的模式和锁定类型,以及传递给mnesia的键号和锁类型:在生成的进程中读取(或使用mnesia:write),可以测试各种锁定行为。

Addendum: See this post by Ulf Wiger on the same topic.

附录:见Ulf Wiger关于同一主题的这篇文章。

Addendum 2: See the section on "Isolation" in the Mnesia user guide.

附录2:请参阅Mnesia用户指南中的“隔离”部分。

Edit: The above was all done on a set-type table, match_object locking behavior might be different on a bag-type table.

编辑:以上内容都是在set-type表上完成的,match -object锁定行为可能在bag-type表上有所不同。

#2


2  

Even though it returns them under a read lock, you can still update them with write afterwards. The whole read/wread thing was just an optimization.

即使它在读锁定下返回它们,您仍然可以通过写入更新它们。整个read / wread只是一个优化。

You can use an ordered_set table to implement this mnesia-trick on compound keys.

您可以使用ordered_set表在复合键上实现此mnesia-trick。

#3


2  

Like this,

喜欢这个,

        case mnesia:match_object(#rec{name=Name, _='_'}) of
            [] -> not_found;
            [First|Rest] -> something
        end,

#4


0  

Can't you just lock the table in your transaction beforehand with mnesia:write_lock_table(Tab) ?

你不能事先用mnesia:write_lock_table(Tab)锁定事务中的表吗?


推荐阅读
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
  • 本文介绍了利用ARMA模型对平稳非白噪声序列进行建模的步骤及代码实现。首先对观察值序列进行样本自相关系数和样本偏自相关系数的计算,然后根据这些系数的性质选择适当的ARMA模型进行拟合,并估计模型中的位置参数。接着进行模型的有效性检验,如果不通过则重新选择模型再拟合,如果通过则进行模型优化。最后利用拟合模型预测序列的未来走势。文章还介绍了绘制时序图、平稳性检验、白噪声检验、确定ARMA阶数和预测未来走势的代码实现。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • Commit1ced2a7433ea8937a1b260ea65d708f32ca7c95eintroduceda+Clonetraitboundtom ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 本文介绍了在使用Laravel和sqlsrv连接到SQL Server 2016时,如何在插入查询中使用输出子句,并返回所需的值。同时讨论了使用CreatedOn字段返回最近创建的行的解决方法以及使用Eloquent模型创建后,值正确插入数据库但没有返回uniqueidentifier字段的问题。最后给出了一个示例代码。 ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
author-avatar
450651324_43c723
这个家伙很懒,什么也没留下!
Tags | 热门标签
RankList | 热门文章
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有