- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我在处理并发时遇到了问题。
在下面的示例中,两个用户 A 和 B 编辑同一张发票并对其进行不同的更改。如果它们都同时单击保存,我希望其中一个成功,另一个失败。否则生成的发票将是不受欢迎的“合并发票”。
这是在 PostgreSQL 中测试的示例(但我认为这个问题应该与数据库无关):
create table invoice (
id int primary key not null,
created date
);
create table invoice_line (
invoice_id int,
line numeric(6),
amount numeric(10,2),
constraint fk_invoice foreign key (invoice_id) references invoice(id)
);
insert into invoice(id, created) values (123, '2018-03-17');
insert into invoice_line (invoice_id, line, amount) values (123, 1, 24);
insert into invoice_line (invoice_id, line, amount) values (123, 2, 26);
所以发票的初始行是:
invoice_id line amount
---------- ---- ------
123 1 24
123 2 26
现在,用户 A 编辑发票,删除第 2 行并点击“保存”:
-- transaction begins
set transaction isolation level serializable;
select * from invoice where id = 123; -- #1 will it block the other thread?
delete invoice_line where invoice_id = 123 and line = 2;
commit; -- User A would expect the invoice to only include line 1.
同时用户 B 编辑发票并添加第 3 行,然后点击保存:
-- transaction begins
set transaction isolation level serializable;
select * from invoice where id = 123; -- #2 will this wait the other thread?
insert into invoice_line (invoice_id, line, amount) values (123, 3, 45);
commit; -- User B would expect the invoice to include lines 1, 2, and 3.
不幸的是,两个事务都成功了,我得到了合并的行(损坏状态):
invoice_id line amount
---------- ---- ------
123 1 24
123 3 45
既然这不是我想要的,我有什么选择来控制并发?
最佳答案
这不是数据库并发问题。数据库的 ACID 属性与完成事务有关,同时保持数据库的完整性。在您描述的情况下,交易是正确的,数据库正在正确处理它们。
您需要的是一种锁定机制,本质上是一种信号量,可以保证在任何时候只有一个用户可以对数据进行写访问。您可能能够依赖数据库锁定机制,在锁定失败时进行捕获。
但是,我建议使用其他两种方法中的一种。如果您对仅在应用程序逻辑中进行更改感到满意,则将锁定机制放在那里。有一个用户可以“锁定”表或记录的地方;然后不要让任何人碰它。
您可以更进一步。您可以要求用户获得表的“所有权”以进行更改。然后,您可以实现一个失败的触发器,除非用户是进行更改的人。
而且,您可能会想到其他解决方案。我真正想指出的是,您的用例超出了 RDBMS 默认执行的范围(因为它们会让两个事务都成功完成)。因此,对于任何数据库(我所熟悉的),您都需要额外的逻辑。
关于sql - 管理数据库并发性的最佳方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49432086/
我有这个代码: private void doSomething() throws InterruptedException { WorkerThread w= new WorkerThrea
我有一个关于并发的简单问题。我正在通过可运行接口(interface)实现线程和并发。如果我首先初始化线程,然后在初始化后单独调用 start,或者如果我初始化线程并从同一个 for 循环中调用 st
我刚开始接触并发,所以如果我问一些明显/愚蠢的问题,请多多包涵。我正在尝试采取第一步来改造我必须利用 Java 货币的模型。没有详细说明,我有一部分模型加载了一些文件,然后在给定请求时它返回文件上的一
我有一个 java 类,它同时被很多线程访问,我想确保它是线程安全的。该类有一个私有(private)字段,它是字符串到字符串列表的映射。我已将 Map 实现为 ConcurrentHashMap 以
正如我们所知,ThreadPoolExecutor 使用一些 BlockingQueue 作为传入任务的队列。我想要的是让 ThreadPoolExecutor 有一个 second 队列,用于准备就
若两个操作同时发生,则称为并发,但事实上,操作是否在时间上重叠并不重要。由于分布式系统复杂的时钟同步问题,现实中很难严格判断两个事件是否同时发生。 为更好定义并发性,并不依赖确切发生时间,即若两个操作
这是计算任意数的阶乘的代码: unsigned long long factorial(int n) { Concurrency::combinable products=Concurrency:
我找不到使用最新的 JAVA 并发例程的这种特定情况的示例。 我计划使用threads 来处理来自开放队列的项目,该队列可能包含 0 到数千个请求。我想限制在任何给定时间有不少于 0 且不超过 10
我正在迈出学习多线程的第一步,并构建一个小测试程序,以便为自己提供一些见解。由于重新排序的可能性,我不相信我的解决方案是安全的.. 这是主程序: public class SynchTest {
我目前正在从事一个搜索引擎项目。为了更快的爬行速度,我在每次链接访问时使用一个 goroutine。但是我遇到了两个让我疑惑的问题! 第一个是代码示例: package main import "fm
我一直在使用 Azure 存储队列通过 QueueTrigger 属性来提供 WebJob。我将 QueueTrigger 配置为将多个项目出队以进行并发处理,如下所示: public static
我正在使用Rails的一些中间件,使用的是最新版本: pfernand-2-mn:~ pfernand$ rails -v Rails 3.1.2 这是rake middleware的输出: use
我一直在尝试使用 Azure Data Lake Store,并且在文档中 Microsoft 声称该系统针对低延迟小文件写入进行了优化。测试它我尝试对单个文件执行大量并行任务写入,但此方法在大多数情
假设我有一个同步的 HashMap,它有一个字符串作为键和一个列表作为值。 Map> map = Collections.synchronizedMap(new HashMap>()); 这个列表是线
这个问题在这里已经有了答案: ConcurrentModificationException for ArrayList [duplicate] (6 个答案) 关闭 9 年前。 我有一个关于我的
问题 当且仅当有空闲 CPU 时,我如何扩展以使用更多线程?像 ThreadPoolExecutor 这样的东西,它在 cpu 核心空闲时使用更多线程,如果没有空闲则更少或只使用一个线程。 用例 现状
这个问题已经有答案了: 已关闭13 年前。 Possible Duplicate: Thread safety in Java class 我正在阅读实践中的 Java 并发,并且我遇到了一个令我困惑
Stroustrup 在C++ 第 4 版第 1193 页中给出了以下示例。我的问题是使用两个线程的并发程序,一个用于 f(),另一个用于 g() 以及 Stroustrup 的声明: if a li
我是一名优秀的程序员,十分优秀!