在事务期间,数据库如何读取数据?

时间:2012-12-06 15:20:23

标签: sql database transactions

让我们假设以下情形:

[Start TX]
SELECT userName FROM users WHERE userId = 1; -- returns x
UPDATE users SET userName = 'y' where userId = 1;
SELECT userName FROM users WHERE userId = 1; -- returns y
[End TX]

数据库如何知道第二次返回y?如何将事务状态集成到查询处理中?

另一种情况:

[Start TX]
SELECT userName FROM users, accounts WHERE useres.userId = accounts.userId AND accounts.balance < 0; -- returns x
UPDATE accounts SET balance = 100 where userId = 1;
SELECT userName FROM users, accounts WHERE useres.userId = accounts.userId AND accounts.balance < 0; -- returns nothing
[End TX]

同样的问题 - 数据库如何通过交易信息运行联接?

3 个答案:

答案 0 :(得分:3)

让我们将数据库表视为B-Tree。让我谈谈数据结构上的几个词 - 我们应该知道B-tree页面组织的主题。假设您有9行(标记自A..I)和B-tree,页面大小= 3。某种方式我们在磁盘上有3个页面

Page1: A,B,C,
Page2: D,E,F
Page3: G,H,I

假设您更改了行E中的内容。您的数据库连接将为page2分配内存并完全加载它(D..F)。您对E进行了更改,但未提交事务。现在您尝试选择(在相同的连接中)。由于内存已包含页面加载,因此SELECT将查看已修改的数据。 但是,如果另一个连接将尝试加载E,则必须加载到内存in-mutable D..F page2。在提交第2页后,所有其他连接都可以看到更改。

当然在现实世界中这个过程要复杂得多。

答案 1 :(得分:2)

我建议阅读以下文章:

SQL Server 2005 Row Versioning-Based Transaction Isolation

虽然这篇文章是关于Sql Server 2005的,但它总结了各种类型的并发控制:

  

有两个主要模型用于控制并发:   悲观并发和乐观并发。

     

在基于悲观并发控制的系统中,锁被用于   阻止用户以影响其他用户的方式修改数据。   应用锁定后,其他用户无法执行该操作   在所有者释放它之前会与锁冲突。这个级别   控制用于存在高争用的环境中   数据,以及使用锁保护数据的成本较低   如果或当并发时回滚事务的成本   冲突发生。

     

相反,在基于乐观并发控制的系统中,用户   在读取数据时不要锁定数据。执行更新时,   系统检查后是否有其他用户更改了数据   它被阅读了。如果另一个用户更新了数据,则会引发错误。   通常,收到错误的用户回滚   事务,然后重新提交事务。这就是所谓的   乐观并发,因为它主要用于其中的环境   数据争用率低,偶尔会有成本   回滚事务会超过锁定数据的成本   正在阅读。

     

使用行版本控制读取已提交的隔离介于两者之间   悲观和乐观的并发。在这种隔离级别下,   读取操作不会获取实时数据的锁定。然而,   对于此隔离,对于更新操作,该过程是相同的   与默认的读提交隔离级别相同的级别:   选择要更新的行是通过使用阻塞扫描来完成的   读取数据值时,将对数据行进行更新锁定。

     另一方面,快照隔离真的很乐观,因为   要修改的数据实际上并未事先锁定,而是   选择进行修改时,数据将被锁定。当一个数据行   满足更新条件,快照事务验证   快照后,另一个事务未修改数据   交易开始了。如果数据未被其他人修改   事务,快照事务锁定数据,更新   数据,释放锁定并继续前进。如果数据已被修改   通过另一个事务,发生更新冲突和快照   交易回滚。

与建议的注释一样,所使用的并发控制类型不仅因所使用的数据库平台而异,而且根据所使用的设置在平台内也有所不同。

答案 2 :(得分:0)

对于任何事务隔离级别,您都可以访问同一事务中的脏数据。