0

我有一个关于分布式事务的问题。假设我有 3 个事务程序:

交易A

  1. 开始
  2. a=读取(A)
  3. b=读取(B)
  4. c=a+b
  5. 写(C,C)
  6. 犯罪

交易 B

  1. 开始
  2. a=读取(A)
  3. a=a+1
  4. 写(一,一)
  5. 犯罪

交易 C

  1. 开始
  2. c=读取(C)
  3. c=c*2
  4. 写(A,C)
  5. 犯罪

所以有5对关键操作:C2-A5、A2-B4、B4-C4、B2-C4、A2-C4。

我应该确保完整性机密性,您知道如何实现吗?

先感谢您!

4

1 回答 1

0

您在帖子中描述的是多用户系统中的常见情况。不同的会话同时使用相同的表和相同的行启动事务。这里有两个问题:

  1. 如果 Session C 在 Session A 更新它之后但在 Session A 提交它的事务之前读取一条记录会发生什么?
  2. 如果会话 C 更新了会话 A 已更新但未提交的同一记录,会发生什么?

(您的场景仅说明了这些问题中的第一个)。

第一个问题的答案是隔离级别。这是跨会话未提交事务的可见性的定义。ANSI 标准规定了四个级别:

  • SERIALIZABLE:从另一个会话中看不到任何更改。
  • REPEATABLE READ:允许幻读,即相同的查询执行两次可能会返回不同的结果。
  • READ COMMITTED:只有已经被另一个会话提交的更改是可见的。
  • READ UNCOMMITTED:diryt readsallowed,即一个会话中未提交的更改在另一个会话中可见。

不同的风格或数据库以不同的方式实现这些,并不是所有的数据库都支持它们。例如,Oracle 只支持 READ COMMITTED 和 SERIALIZABLE,它把 SERIALIZABLE 实现为一个 snapsot(即它是一个只读事务)。但是,它使用多版本并发控制来防止 READ COMMITTED 事务中的不可重复读取。

所以,回到你的问题,答案是:设置适当的隔离级别。合适的级别取决于您的数据库支持的级别以及您希望发生的行为。可能您想要 READ COMMITTED 或 SERIALIZABLE,即您希望您的事务在数据值与事务开始一致的基础上继续进行。

至于另一件事,答案更简单:事务必须在开始更新表之前对表或最好只对所需的行进行锁定。这确保事务可以继续更改这些值而不会导致死锁。这称为悲观锁定。这在使用连接池的应用程序(即大多数基于 Web 的应用程序)中是不可能的,而且情况要复杂得多。

于 2010-05-24T12:35:07.237 回答