数据库事务是否会阻止竞争条件?
|
我尚不完全清楚数据库系统中的事务是做什么的。我知道他们可以用来完全回滚更新列表(例如,从一个帐户中扣除资金,然后将其添加到另一个帐户中),但这是他们所做的全部吗?特别是,它们可以用于预防比赛状况吗?例如:
// Java/JPA example
em.getTransaction().begin();
User u = em.find(User.class, 123);
u.credits += 10;
em.persist(u); // Note added in 2016: this line is actually not needed
em.getTransaction().commit();
(我知道这可能写为一个更新查询,但并非总是如此)
该代码是否可以防止竞争条件?
我对MySQL5 + InnoDB最为感兴趣,但也欢迎提供一般答案。
没有找到相关结果
已邀请:
4 个回复
鞋扣蚊冈借
隔离的情况下。 一些RDBMS具有比其他RDBMS更强大的功能。例如,PostgreSQL 9.2和更高版本具有很好的“ 2”隔离度,可检测到事务之间大多数(但不是全部)可能的交互,并中止其中一个冲突的事务。因此它可以非常安全地并行运行事务。 很少有系统具有真正完美的“ 2”隔离,可以防止所有可能的争用和异常,包括锁升级和锁排序死锁之类的问题。 即使隔离度很高,某些系统(如PostgreSQL)也会中止冲突的事务,而不是让它们等待并串行运行它们。您的应用必须记住它在做什么,然后重试该事务。因此,尽管事务阻止了与并发相关的异常存储到数据库,但是这样做对应用程序而言并不透明。 原子性 可以说,数据库事务的主要目的是提供原子提交。在提交事务之前,这些更改才会生效。提交后,就其他事务而言,所有更改均在同一瞬间生效。任何事务都无法看到事务所做的1,2,2部分更改。同样,如果您选择“ 5”,则任何其他交易都不会看到该交易的更改;好像您的交易不存在。 这就是ACID中的A。 耐用性 另一个是耐久性-ACID中的D。它指定当您提交事务时,必须将其真正保存到可以避免掉电或突然重启等故障的存储中。 一致性: 参见维基百科 乐观并发控制 对于Hibernate,EclipseLink等ORM,通常不使用锁定和/或较高的隔离级别,而使用乐观并发控制(通常称为“乐观锁定”)来克服较弱的隔离级别的局限性,同时又保留了性能。 。 这种方法的主要功能是,它使您可以跨多个事务处理工作,这对于具有大量用户并且与任何给定用户进行交互之间可能存在较长延迟的系统来说,是一个很大的优势。 参考文献 除了文本链接之外,请参见有关锁定,隔离和并发的PostgreSQL文档章节。即使您使用的是其他RDBMS,您也将从其解释的概念中学到很多东西。 为了简单起见,这里我忽略了很少实现的“ 6”隔离级别;它允许脏读。 2正如@meriton指出的,推论不一定是正确的。幻像读取出现在
以下。正在进行的事务的一部分看不到某些更改(尚未提交的事务),然后正在进行的事务的下一部分确实在另一事务提交时看到了更改。 3好吧,IIRC SQLite2通过在尝试写操作时锁定整个数据库来做到这一点,但这并不是我所说的并发问题的理想解决方案。
漂汀拦
假设这返回了(123,13,100)。
该数据库告诉我们更新了多少行。如果它是一个,则没有冲突的更新。如果为零,则发生冲突的更新,并且JPA提供程序将执行
并引发异常,以便应用程序代码可以处理失败的事务,例如通过重试。 简介:无论采用哪种方法,都可以确保您的陈述不受比赛条件的影响。
磐乓铝举
曝匿弄罚