分布式事务中的完整性和保密性
我有一个关于分布式事务的问题。假设我有 3 个事务程序:
事务 A
- 开始
- a=read(A)
- b=read(B)
- c=a+b
- write(C,c)
- 提交
事务 B
- begin
- a=read(A)
- a=a+1
- write(A,a)
- commit
事务C
- begin
- c=read(C)
- c=c*2
- write(A,c)
- commit
所以有是 5 对关键操作:C2-A5、A2-B4、B4-C4、B2-C4、A2-C4。
我应该确保完整性和保密,你知道如何实现吗?
先感谢您!
I've a question regarding distributed transactions. Let's assume I have 3 transaction programs:
Transaction A
- begin
- a=read(A)
- b=read(B)
- c=a+b
- write(C,c)
- commit
Transaction B
- begin
- a=read(A)
- a=a+1
- write(A,a)
- commit
Transaction C
- begin
- c=read(C)
- c=c*2
- write(A,c)
- commit
So there are 5 pairs of critical operations: C2-A5, A2-B4, B4-C4, B2-C4, A2-C4.
I should ensure integrity and confidentiality, do you have any idea of how to achieve it?
Thank you in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您在帖子中描述的是多用户系统中的常见情况。不同的会话同时使用相同的表和相同的行启动事务。这里有两个问题:
(您的场景仅说明了第一个问题)。
第一个问题的答案是 ioslation level。这是跨会话未提交事务的可见性的定义。 ANSI 标准指定了四个级别:
不同的风格或数据库以不同的方式实现这些,并且并非所有数据库都支持所有这些。例如,Oracle仅支持READ COMMITTED和SERIALIZABLE,并且它将SERIALIZABLE实现为快照(即它是只读事务)。但是,它使用多版本并发控制来防止 READ COMMITTED 事务中的不可重复读取。
因此,回到您的问题,答案是:设置适当的隔离级别。适当的级别取决于您的数据库支持的级别以及您希望发生的行为。也许您想要 READ COMMITTED 或 SERIALIZABLE,也就是说您希望事务在数据值与事务开始一致的基础上继续进行。
至于其他问题,答案更简单:事务必须在表上发出锁,或者最好只在所需的行上发出锁,然后才能开始更新它们。这确保事务可以继续更改这些值而不会导致死锁。这称为悲观锁定。这在使用连接池的应用程序(即大多数基于 Web 的应用程序)中是不可能的,而且情况更加糟糕。
What you have described in your post is a common situation in multi-user systems. Different sessions simultaneously start transactions using the same tables and indeed the same rows. There are two issues here:
(Your scenario only illustrates the first of these issues).
The answer to the first question is ioslation level. This is the definition of the visibility of uncommmitted transactions across sessions. The ANSI standard specifies four levels:
Different flavours or database implement these in different fashions, and not all databases support all of them. For instance, Oracle only supports READ COMMITTED and SERIALIZABLE, and it implements SERIALIZABLE as a snapsot (i.e. it is a read-only transaction). However, it uses multiversion concurrency control to prevent non-repeatable reads in READ COMMITTED transactions.
So, coming back to your question, the answer is: set the appropriate Isolation Level. What the appropriate level is depends on what levels your database supports, and what behaviour you wish to happen. Probably you want READ COMMITTED or SERIALIZABLE, that is you want your transactions to proceed on the basis of data values being consistent with the start of the transaction.
As to the other matter, the answer is simpler: transactions must issue locks on tables or preferably just the required rows, before they start to update them. This ensures that the transaction can proceed to change those values without causing a deadlock. This is called pessimistic locking. It is not possible in applications which use connection pooling (i.e. most web-based applications), and the situation there is much gnarlier.