我对标题中的主题有几个问题.首先,假设我们使用JDBC,并且我们有2个事务T1和T2.在T1中,我们在一个特定行上执行select语句.然后我们在该行上执行更新.在事务T2中,我们在同一行上执行select语句.
以下是问题:
1)事务T1何时获取上述行的锁定?我认为它发生在select语句执行期间?
2)事务T1保持锁定多长时间?它是否在提交/回滚事务之前保留它,或者在此之前释放锁定?
3)隔离级别是否控制使用何种类型的锁?例如:
a)如果我们在事务T2上使用读提交的隔离级别,这是否意味着T2将对select语句使用共享读锁定,这样在T1更新的情况下,已经T2的行将无法访问该行(避免脏读),如果T1没有更新行,T2会对该行有读取权限吗?
b)如果我们在事务T2上使用读取未提交的隔离级别,这是否意味着T2将对select语句使用no-lock,因此即使它被T1修改(允许脏读),它也可以读取数据.
那么,最让我烦恼的问题是谁能控制决定使用什么类型的锁?是隔离级别的交易,还是有其他方式?
4)如果对问题3的回答是肯定的(隔离级别控制使用的是什么锁),那么如果我们使用jdbc而不是mysql数据库会发生什么,我们使用select for update或select share in share mode constructs?我记得第一个是独占锁,而第二个是共享读锁.它将如何反映我们的事务隔离级别?
5)在可重复的读隔离级别的情况下获得什么样的锁?假设我们的T2(具有可重复的读隔离级别)在同一行上有两个select语句,而T1与之前相同.首先在T2中执行一个select语句,然后执行并提交T1,然后执行T2第二次选择.这种情况甚至可能吗?如果事务保持锁定直到它们被提交/回滚,我假设在T2完成之前T1将无法获得更新的独占锁定?
编辑:还有一个问题:
6)在多版本并发控制系统中,当我们设置可序列化的隔离级别时,将回滚尝试更新由另一个事务B更新的某一行的事务A(B在A启动后更新该行).我想问一下在乐观锁定场景中发生的事情是不是很相似?
提前致谢.
最佳答案 你的问题很好.了解获取哪种锁可以深入理解DBMS.在SQL Server中,在所有隔离级别下(Read Uncommitted,Read Committed(默认),Repeatable Reads,Serializable)为Write操作获取独占锁.
无论隔离级别如何,当事务结束时都会释放独占锁.
隔离级别之间的差异是指获取/释放共享(读取)锁定的方式.
在Read Uncommitted隔离级别下,不会获取共享锁.在此隔离级别下,可能会发生称为“脏读”的并发问题.
在Read Committed isolation level下,为相关记录获取共享锁.当前指令结束时释放共享锁.此隔离级别可防止“脏读”,但由于记录可由其他并发事务更新,因此可能会发生“不可重复读取”或“幻像读取”.
在“可重复读取”隔离级别下,将为事务持续时间获取共享锁.防止“脏读”和“不可重复读”,但仍可能发生“幻读”.
在Serializable隔离级别下,将为事务持续时间获取范围内的共享锁.上述并发问题均未发生,但性能大幅降低,存在死锁发生的风险.