Questions tagged «concurrency»

对于当多个用户或进程同时访问或修改数据库系统中的共享信息时出现的问题。

1
Postgres UPDATE…LIMIT 1
我有一个Postgres数据库,其中包含有关服务器群集的详细信息,例如服务器状态(“活动”,“备用”等)。活动服务器在任何时候都可能需要故障转移到备用服务器,而且我不在乎使用哪个备用服务器。 我希望数据库查询更改备用数据库(仅一个)的状态,并返回要使用的服务器IP。选择可以是任意的:由于服务器的状态随查询而变化,因此选择哪个备用数据库都无关紧要。 是否可以将查询限制为仅一次更新? 这是我到目前为止的内容: UPDATE server_info SET status = 'active' WHERE status = 'standby' [[LIMIT 1???]] RETURNING server_ip; Postgres不喜欢这样。我可以做些什么?

5
在PostgreSQL中并发DELETE / INSERT锁定问题
这很简单,但是我对PG(v9.0)的功能感到困惑。我们从一个简单的表开始: CREATE TABLE test (id INT PRIMARY KEY); 和几行: INSERT INTO TEST VALUES (1); INSERT INTO TEST VALUES (2); 使用我最喜欢的JDBC查询工具(ExecuteQuery),我将两个会话窗口连接到该表所在的数据库。它们都是事务性的(即auto-commit = false)。我们称它们为S1和S2。 每个代码都使用相同的代码: 1:DELETE FROM test WHERE id=1; 2:INSERT INTO test VALUES (1); 3:COMMIT; 现在,以慢速运行此命令,一次在Windows中执行一次。 S1-1 runs (1 row deleted) S2-1 runs (but is blocked since S1 has a write …

4
您如何测试数据库中的竞争条件?
我尝试编写数据库代码以确保它不受争用条件的影响,以确保锁定了正确的行或表。但是我经常想知道:我的代码正确吗?是否可以强迫任何现有的竞赛条件表现出来?我想确保,如果它们确实发生在生产环境中,我的应用程序将做正确的事情。 我通常确切地知道哪个并发查询可能会导致问题,但是我不知道如何强制它们并发运行以查看是否发生了正确的行为(例如,我使用了正确的锁类型),正确的错误是抛出等 注意:我使用PostgreSQL和Perl,因此,如果不能一概而论,就应该重新标记它。 更新:如果解决方案是程序化的,我希望使用它。这样,我可以编写自动化测试以确保没有回归。

3
使用SELECT-UPDATE模式时管理并发
假设您有以下代码(请忽略这很糟糕): BEGIN TRAN; DECLARE @id int SELECT @id = id + 1 FROM TableA; UPDATE TableA SET id = @id; --TableA must have only one row, apparently! COMMIT TRAN; -- @id is returned to the client or used somewhere else 在我看来,这不能正确地管理并发。仅仅因为您有一笔交易并不意味着其他人不会获得与您获得更新语句之前相同的值。 现在,将代码保持原样(我意识到这可以更好地作为单个语句处理,甚至可以使用自动增量/标识列更好地进行处理),有什么确定的方法可以使其正确处理并发并防止允许两个客户端获得相同竞争条件的竞争条件。 id值? 我非常确定,将WITH (UPDLOCK, HOLDLOCK)SELECT 添加到SELECT即可。该SERIALIZABLE事务隔离级别(因为它拒绝任何人阅读你做了什么,直到移植是在将似乎工作,以及UPDATE:这是假见马丁的答案)。真的吗?他们俩会平等地工作吗?是一个比另一个更好的选择吗? 想象一下,做比ID更新更合法的事情-基于需要更新的读取进行一些计算。可能涉及许多表,其中一些将要写入,而有些则不会。最佳做法是什么? 写完这个问题后,我认为锁定提示会更好,因为那样的话,您只锁定了所需的表,但是我很感谢任何人的投入。 PS:不,我不知道最佳答案,并且确实希望得到更好的理解!:)

6
我可以依靠顺序读取SQL Server身份值吗?
TL; DR:下面的问题归结为:插入行时,在生成新Identity值和锁定聚集索引中的相应行键之间是否存在机会之窗,外部观察者可以看到更新的值 Identity并发交易插入的价值?(在SQL Server中。) 详细版本 我有一个带有Identity名为的列的SQL Server表CheckpointSequence,这是表的聚集索引(也具有许多其他非聚集索引)的键。通过多个并发进程和线程将行插入表中(处于隔离级别READ COMMITTED,并且没有IDENTITY_INSERT)。同时,有些进程会定期从聚簇索引中读取行,并按该CheckpointSequence列排序(也处于隔离级别READ COMMITTED,并且该READ COMMITTED SNAPSHOT选项处于关闭状态)。 我目前依靠这样的事实,即读取过程永远不会“跳过”检查点。我的问题是:我可以依靠这个财产吗?如果没有,我该怎么做才能实现? 示例:当插入具有标识值1、2、3、4和5 的行时,阅读器在看到具有值4的行之前必须看不到具有值5的行。测试表明该查询包含一个ORDER BY CheckpointSequence子句(和一个WHERE CheckpointSequence > -1子句),只要要读取第4行但尚未提交,就可靠地阻塞,即使第5行已经提交。 我认为至少从理论上讲,这里可能存在一种竞争条件,可能会导致这一假设被打破。不幸的是,关于多个并发事务的工作方式的文档Identity并没有太多说明Identity,而只是说“每个新值都是基于当前的种子和增量生成的”。和“特定交易的每个新值都与表上的其他并发交易不同”。(MSDN) 我的推理是,它必须以这种方式工作: 事务开始(显式或隐式)。 生成标识值(X)。 根据身份值在聚集索引上获取相应的行锁(除非发生锁升级,在这种情况下整个表都被锁定)。 该行已插入。 事务已提交(可能要花很多时间),因此将再次删除该锁。 我认为在第2步和第3步之间,有一个很小的窗口, 并发会话可以生成下一个标识值(X + 1)并执行所有其余步骤, 因此,允许阅读者恰好在该时间点阅读值X + 1,而忽略了X的值。 当然,这种可能性似乎很小。但仍然-可能会发生。可以吗 (如果您对上下文感兴趣:这是NEventStore的SQL Persistence Engine的实现。NEventStore实现一个仅附加事件存储,其中每个事件都获得一个新的,升序的检查点序列号。客户端从按检查点排序的事件存储中读取事件为了执行各种计算,一旦处理了带有检查点X的事件,客户就只考虑“较新的”事件,即带有检查点X + 1及更高版本的事件,因此,至关重要的是永远不能跳过事件,因为它们再也不会被考虑了,我目前正在尝试确定Identity基于-checkpoint的实现是否满足此要求。这些是所使用的确切SQL语句:Schema,Writer的query,读者查询。) 如果我是对的,并且可能出现上述情况,那么我只能看到两种处理方式,但都不令人满意: 在看到X之前看到检查点序列值X + 1时,关闭X + 1并稍后再试。但是,由于Identity当然会产生间隙(例如,当事务回滚时),因此X可能永远不会出现。 因此,相同的方法,但是在n毫秒后接受间隔。但是,我应该假定n的值是多少? 还有更好的主意吗?


1
阅读部分更新的行?
假设我有两个查询,分别在SSMS中的两个会话中运行: 第一届会议: UPDATE Person SET Name='Jonny', Surname='Cage' WHERE Id=42 第二届会议: SELECT Name, Surname FROM Person WITH(NOLOCK) WHERE Id > 30 该SELECT语句是否可能读取半更新的行,例如带有Name = 'Jonny'和的行Surname = 'Goody'? 查询几乎在单独的会话中同时执行。

3
如果不存在,则插入
我在存储过程中的插入出现并发问题。该过程的相关部分是: select @_id = Id from table1 where othervalue = @_othervalue IF( @_id IS NULL) BEGIN insert into table1 (othervalue) values (@_othervalue) select @_id = Id from table1 where othervalue = @_othervalue END 当我们同时运行3或4个这些存储的proc时,有时会得到多个插入。 我打算像这样修复此问题: insert into table1 (othervalue) select TOP(1) @_othervalue as othervalue from table1 WITH(UPDLOCK) where NOT EXISTS …

1
高并发存储系统
想象一下您的需求是,您有3个巨大的表(结构化数据),每个表有300亿行(总大小为4TB),并且许多并发用户(远程LAN机器上的并行os线程)将需要读取一部分通过他们的SELELCT WHERE GROUPBY查询和高度并发的数据,例如,同时进行10,000次并发读取,并且用户也需要将这些数据高度并发地插入(不更新)数据到这些表中,例如2000个并发写入器(遍及数据中心LAN网络) 。用户可能希望尽快从该存储中读取和插入数据,每次读取和写入将发生在毫秒到1秒范围内。 您推荐什么技术来满足这种要求?是否有任何数据存储或键值存储可以做到这一点?不能选择云。 一些说明: 用户不必立即查看数据,最终的一致性是可以接受的。数据可以通过存储可以提供的任何驱动程序进行访问,而用户又仅仅是在数据中心的远程计算机上运行的线程。查询大多类似于SELECT WHERE GROUPBY。 数据采用表格格式,每行约60个字节。 我无法使用DynamoDB或类似解决方案的无云选项。我必须能够在数据中心内部托管它。 可以一直读取表中的所有数据,并且使用模式是不可预测的。没有联接或超长查询。不需要DR,但是需要合理的HA,但是不必花哨。每个读者都基于其where子句获得了一批行,而这些子句与行并不是真正相关。我们可能每行的长度可以固定,但是我希望存储层对此有所担心。 另外,我最大的担心是与并发读取一起发生的所有那些并发写入。 非常感谢您对此的见解。 更重要的是,我有三个表,每个表有300亿行包含不同的对象类型


1
锁定Postgres以进行UPDATE / INSERT组合
我有两张桌子。一个是日志表;另一个是日志表。另一个实质上包含只能使用一次的优惠券代码。 用户需要能够兑换优惠券,这将在日志表中插入一行并将优惠券标记为已使用(通过将used列更新为true)。 自然,这里存在明显的比赛条件/安全性问题。 在过去的mySQL世界中,我做过类似的事情。在那个世界中,我将全局锁定两个表,在一次只能执行一次的前提下,确保逻辑安全,然后在完成后解锁表。 Postgres中有更好的方法吗?特别是,我担心锁是全局的,但不一定是全局的-我真的只需要确保没有其他人试图输入该特定代码,那么也许行级锁会起作用吗?

2
LATCH_EX等待资源METADATA_SEQUENCE_GENERATOR
我们有一个生成库存报告的过程。在客户端,该过程拆分可配置数量的工作线程,以为报告构建大量数据,这些数据对应于许多商店(可能是数千个,通常是几十个)中的一个商店。每个工作线程都调用一个执行存储过程的Web服务。 用于处理每个块的数据库过程将一堆数据收集到#Temporary表中。在每个处理块的末尾,数据将被写入tempdb中的永久表。最后,在该过程结束时,客户端上的一个线程从永久tempdb表中请求所有数据。 运行此报告的用户越多,获取速度就越慢。我分析了数据库中的活动。在某一时刻,我看到35个单独的请求在流程的某一时刻全部被阻塞。所有这些SPID LATCH_EX在资源上的类型等待时间约为50 ms METADATA_SEQUENCE_GENERATOR (00000010E13CA1A8)。一个SPID拥有此资源,而其他所有SPID都被阻止。我没有在网络搜索中找到有关此等待资源的任何信息。 我们正在使用的tempdb中的表确实有一IDENTITY(1,1)列。这些SPID是否正在等待IDENTITY列?我们可以使用什么方法来减少或消除阻塞? 该服务器是集群的一部分。该服务器在64位Windows 2008 R2 Enterprise上运行64位SQL Server 2012 Standard Edition SP1。该服务器具有64 GB RAM和48个处理器,但是该数据库是标准版本,因此只能使用16个。 (请注意,我对在tempdb中使用永久表来保存所有这些数据的设计并不感到兴奋。对此进行更改将是一个有趣的技术和政治挑战,但我愿意接受建议。) 更新4/23/2013 我们已经与Microsoft开立了支持案例。随着我们了解更多信息,我将不断更新此问题。 更新5/10/2013 SQL Server支持工程师同意等待是由IDENTITY列引起的。删除IDENTITY消除了等待。我们无法在SQL 2008 R2上重复该问题;它仅发生在SQL 2012上。


1
将Select语句放入事务中
这两个查询之间有什么区别: START TRANSACTION; SELECT * FROM orders WHERE id=1; UPDATE orders SET username='John' WHERE id=1; COMMIT; 而且没有交易: SELECT * FROM orders WHERE id=1; UPDATE orders SET username='John' WHERE id=1; 进行SELECT内部交易有什么影响? 如果在这两种情况DELETE FROM orders WHERE id=1之后都SELECT在另一个会话中被调用,它将在何时进行处理?

3
可重复读中的不一致
http://www.postgresql.org/docs/9.2/static/transaction-iso.html 可重复读取模式提供了严格的保证,即每个事务都能看到数据库的完全稳定的视图。但是,此视图不一定总是与同一级别的并发事务的某些串行(一次一个)执行一致。例如,即使是该级别的只读事务,也可能会看到更新了控制记录以显示批次已完成,但是看不到逻辑上属于该批次的详细记录之一,因为它读取了控制记录的较早版本。 。如果不谨慎使用显式锁来阻止冲突的事务,则试图通过在此隔离级别运行的事务来强制执行业务规则的尝试将无法正常工作。 这不是幻像读取吗,在可重复读取模式下是不可能的? 该文档说,在可重复读取事务中的查询在事务开始时看到快照,那么查询怎么可能读取不一致的数据?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.