假设我有以下情况:
T1:
Update Student Set GPA=(1.1)*GPA Where sizeHS > 2500
T2:
Set Transaction isolation Level Read Committed;
Select Avg(GPA) From Student;
Select Max(GPA) From Student;
如果 T1 在 T2 中的两个 select 语句之间运行,那么我可以清楚地看到第一个 select 语句将考虑 T1 更新,而第二个 select 语句则不会。
但我想知道 T1 是否可以将自己完全交错在第一个 select 语句中?即,第一个 select 语句将读取一半的学生,以计算 Avg(GPA),并在进行过程中为每一行获取和释放行锁。然后 T1 进来,取出必要的写锁,更新它想要的内容,然后提交。然后第一个 Select 语句返回并读取另一半学生,现在有新的更新。因此,我们甚至无法正确计算 Avg(GPA),即使它是一个单一的语句,因为我们阅读的学生中有一半已经收到了更新的分数,而另一半则没有。看起来这种不一致是允许在已提交读下发生的,但我只是想验证一下。
在相关说明中,我正在阅读此页面:https://learn.microsoft.com/en-us/sql/t-sql/statements/set-transaction-isolation-level-transact-sql ?view=sql-server- ver16,特别是 READ_COMMITTED_SNAPSHOT 下的一行:
当读取下一页时,页锁被释放,当语句完成时,表锁被释放。
我想知道表锁是什么意思?当然,我认为它不仅会停止对表的所有修改,还会执行其他操作,例如在 select 语句期间停止插入和删除?
所有读已提交保证是您只读取已提交的数据。
它不保证其他任何事情。
使用提交读锁定隔离,即使根本没有更新 GPA,扫描仍然可能返回不一致的结果(行丢失或在扫描期间在索引中移动时读取了两次)。
类似地,行肯定可以按顺序进行处理,
UPDATE
这意味着扫描会看到一些“更新前”行(在更新到达它们之前)和一些“更新后”行(更新完成后)。坚定的)。您可以通过使用已提交读的快照隔离实现来避免这些问题 - 这使用行版本来获取每个语句在该语句开始执行时的事务上一致的数据快照。
关于你的问题标题...
这与“原子性”(ACID 中的“A”)无关。原子性只是保证事务要么成功,要么完全回滚。这是关于“隔离”的。