事务、锁、隔离级别

5
我对标题中的主题有几个问题。首先,我们假设使用JDBC,并且有2个事务T1和T2。在T1中,我们执行了一条特定行的选择语句。然后我们在该行上执行更新。在事务T2中,我们对同一行执行了select语句。
以下是问题:
1)事务T1何时获取提到的行锁?我认为它会在选择语句执行期间发生?
2)事务T1持有锁多长时间?它是否一直持有锁,直到事务提交/回滚,或者在那之前释放锁?
3)隔离级别是否控制所使用的锁类型?例如:
a)如果在事务T2上使用“读提交”隔离级别,这是否意味着T2将使用共享读锁进行选择语句,以便在T1已经更新行的情况下,T2将无法访问该行(避免脏读取 ),并且在T1尚未更新行的情况下,T2将可以读取该行?
b)如果在事务T2上使用“未提交读”隔离级别,这是否意味着T2将使用无锁选择语句,因此即使T1正在修改数据,它也可以读取数据(允许脏读取)。
因此,最困扰我的问题是谁掌控决定应用哪种类型的锁?是事务的隔离级别,还是存在其他方法?
4)如果问题3的答案为肯定(隔离级别控制使用哪些锁),那么如果例如在MySQL数据库上使用jdbc,并且我们使用选择以进行更新或选择锁定共享模式构造,会发生什么情况?正如我所记得的那样,第一个是独占锁,而第二个是共享读锁。它将如何反映在我们的事务隔离级别上?
5)在“可重复读”隔离级别的情况下获取了什么样的锁?假设我们的T2(具有可重复读隔离级别)在同一行上有两个选择语句,而T1与之前相同。在T2中执行了第一次选择语句,然后执行并提交了T1,之后执行了T2的第二次选择语句。这种情况甚至可能吗?如果事务保持它们的锁直到提交/回滚,我认为T1将无法获得独占锁以进行更新,直到T2完成?
编辑:再问一个问题:
6)在多版本并发控制系统中,当我们设置“串行化”隔离级别时,尝试更新由另一个事务B更新的某些行的事务A(B在A开始后更新了该行)将被回滚。我想问,这与乐观锁定场景发生的情况非常相似吗?
提前致谢。

1
这是很多问题...答案取决于使用的具体DB/版本...所以我们正在谈论哪个DB? - Yahia
好的,假设它是 MySQL 5.5 :) - Kovasandra
好的 - 这还不够,因为MySQL可以与不同的存储引擎一起使用,这些存储引擎在事务方面的行为也有很大的不同,所以:使用哪个存储引擎? - Yahia
看,我可以说InnoDB,但我认为它使用多版本并发控制,而我的问题更与基于经典锁定的并发控制有关。但好吧,让我们说它是InnoDB存储引擎。我甚至还有一个关于mvcc及其与乐观锁定的关系的问题 :) - Kovasandra
1
有关一些常规问题,请参见http://dev.mysql.com/doc/refman/5.1/en/set-transaction.html#isolevel_read-committed-虽然我认为这个问题属于serverfault.com。 - Yahia
1个回答

6
你的问题很好。理解所获得的锁的类型可以深入了解数据库管理系统。在SQL Server中,对于所有隔离级别(未提交读取、已提交读取(默认)、可重复读取和串行化),写操作都会获得独占锁。
无论隔离级别如何,独占锁在事务结束时释放。
隔离级别之间的区别在于获取/释放共享(读取)锁的方式。
在“读未提交”隔离级别下,不会获取任何共享锁。在这个隔离级别下,可能会出现称为“脏读”的并发问题。
在“已提交读取”隔离级别下,为相关记录获取共享锁。当当前指令结束时,共享锁被释放。这个隔离级别可以防止“脏读”,但由于记录可能被其他并发事务更新,“不可重复读取”或“幻读”可能会发生。
在“可重复读取”隔离级别下,为事务持续时间获取共享锁。可以防止“脏读”和“不可重复读取”,但是“幻读”仍然可能发生。
在“串行化”隔离级别下,为事务持续时间获取范围共享锁。不会发生上述任何并发问题,但性能会大大降低,并且存在死锁的风险。

非常好的解释 - Basil Kosovan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接