当前位置: 首页 > 面试题库 >

更新竞赛条件Postgres的位置(已读)

融泓
2023-03-14
问题内容

我正在尝试编写一个查询,仅当用户打开的活动声明不超过两个时,才将“声明”表中的行更新为活动状态。因此,它是用于数据的完整性非常重要的是,用户 永远
有两个以上的主动要求在任何给定的时间打开。

我在并发环境中运行此查询,因此两个进程可能同时执行此查询。我也在默认Read Committed隔离级别下运行它。

我想知道是否由于子选择和更新子句之间的竞争条件而在某个时候打开一个用户有两个以上的主动声明的可能性。

值得一提的是,对于此查询,性能几乎不如数据完整性那么重要。

update claim
set is_active = '1'
where claim.id = %s
and (2 > (select count(*)
          from claim as active_claim
          where active_claim.user_id = %s
          and active_claim.is_active = '1'))

问题答案:

是的,这绝对有可能导致两个以上的活动声明,因为并发事务无法看到彼此的更改,因此两个或多个并发执行将同时看到2个声明,并且都将继续更新其目标声明以使它们积极的。

餐桌锁

最简单的选择是:

BEGIN;
LOCK TABLE claim IN EXCLUSIVE MODE;
UPDATE ...
COMMIT;

…但这是一个非常沉重的解决方案。

用户对象上的行级锁定

假设您有一张user声明所有者的表格,则应改为:

SELECT 1 FROM user WHERE user_id = whatever FOR UPDATE

在同一笔交易中,在运行您的之前UPDATE。这样,您将在用户上持有排他的行锁,而其他SELECT ... FOR UPDATE语句将在您的锁上阻塞。此锁还将阻止UPDATEs和删除user;如果没有or子句,它将 不会 阻止SELECT用户的plain
s 。FOR UPDATE``FOR SHARE

请参见PostgreSQL手册中的显式锁定。

SERIALIZABLE 隔离

另一种方法是使用SERIALIZABLE隔离。PostgreSQL
9.2及更高版本具有事务相关性检测功能,在上面给出的示例中,这将导致所有冲突事务(只有一个冲突事务)中止并发生序列化失败。因此,您的应用必须记住启动事务时尝试执行的操作,并能够捕获错误,检测到错误是序列化失败,并在序列化失败后重试。

请参见PostgreSQL手册中的事务隔离。

咨询锁

有时,没有好的候选对象需要进行行锁定,并且由于某种原因或其他可序列化的隔离措施无法解决该问题或由于其他原因而无法使用。事实并非如此,这只是一般信息。

在这种情况下,您可以使用PostgreSQL的咨询锁来锁定任意数值。在这种情况下,您会pg_advisory_xact_lock(active_claim.user_id)举个例子。显式锁定章节提供了更多信息。



 类似资料:
  • 我有以下资料: streamB中的消息需要使用表A中的数据进行丰富。 示例数据: 在一个完美的世界里,我想做什么 不幸的是,这对我不起作用,因为我的数据是这样的:每次将消息写入主题a时,相应的消息也会写入主题B(源是单个DB事务)。现在,在这个初始“创建”事务之后,主题B将继续接收更多消息。有时,主题B上会出现每秒数个事件,但对于给定的键,也可能出现连续事件间隔数小时的情况。 简单的解决方案不起作

  • 9.1. 竞争条件 在一个线性(就是说只有一个goroutine的)的程序中,程序的执行顺序只由程序的逻辑来决定。例如,我们有一段语句序列,第一个在第二个之前(废话),以此类推。在有两个或更多goroutine的程序中,每一个goroutine内的语句也是按照既定的顺序去执行的,但是一般情况下我们没法去知道分别位于两个goroutine的事件x和y的执行顺序,x是在y之前还是之后还是同时发生是没法

  • 我正在做分类帐模块。在这个过程中,我必须按顺序完成这些任务 从源中选择余额(table 1 row1) 从目标中选择余额(table 1 row2) 用一些逻辑修改余额 更新源的余额(table 1 row1) 更新目标余额(table 1 row2) 提交更改 将事务插入到事件表中。 在多线程环境中,线程在前一个线程更新和提交之前获得余额。在Postgres中,锁被强加给正在被访问的行,直到线程

  • 1 竞态条件漏洞 下面的代码段属于某个特权程序(即 Set-UID 程序),它使用 Root 权限运行。 1: if (!access("/tmp/X", W_OK)) { 2: /* the real user ID has access right */ 3: f = open("/tmp/X", O_WRITE); 4 : write_to_file(f); 5: } 6: else

  • 竞态条件是由和事件时间相关的意料之外的依赖所导致的反常行为。 换句话说,一个程序员不正确的假设一个特殊的事件总是在另一个事件之前发生。 一些通常的导致竞态条件的原因是信号,存取检查和打开文件操作。 由于信号生来就是异步事件所以在处理他们时要特别当心。存取检查中使 用access(2)然后使用open(2) 是很明显的非原子操作。用户可以在两次调用中移走文件。换言之,有特 权的程序应该使用seteu

  • 问题内容: 这是带有潜在竞争条件的Django视图的简单示例: 竞争条件应该非常明显:用户可以两次发出此请求,并且该应用程序可能同时执行,从而导致其中一个请求覆盖另一个请求。 假设函数相对复杂,并且基于无法放置在单个存储过程中并且难以放置在存储过程中的各种奇怪的东西进行计算。 所以这是我的问题:django可使用哪种锁定机制来处理类似的情况? 问题答案: Django 1.4+支持select_f