事务下的 Select Max(field) 会锁定任何行吗?

Will Select Max(field) under transaction lock any rows?

我们有这段代码,我想知道,在正常的 Ado.net 事务下,它实际上会锁定任何行吗?示例:

var sql1 = "SELECT MAX(entryNum) FROM tbl1 WHERE processNum = 1";
var cmd = new SqlCommand(sql1, conn, tran);
var newEntryNum = cmd.ExecuteScalar();
. . . . . . 
var sql2 = "INSERT INTO tbl2 (entryNum) VALUES (" + newEntryNum  + ")";
cmd = new SqlCommand(sql2, conn, tran);

在第一个select中,它会用processNum = 1锁定记录吗?在我看来,似乎什么都不会被锁定。是否有充分的理由按照交易的方式执行 SELECT MAX

通过锁定一行,我假设你的意思是防止另一个事务修改该行?我提到这一点是因为数据库在不同的时间放置各种锁,从而导致不同的锁定行为。

无论如何,你问题的答案与编程语言或ADO.NET无关。它完全取决于用于事务的数据库和隔离级别。

例如,在 SQL 服务器中,如果您 运行 处于 read committed 模式(这是我通常所说的),一旦 select 查询完成后,它不会阻止另一个事务修改带有 processNum = 1.

的行

但是,如果您处于 repeatable readserializable 模式,那么是的,执行 select 查询将锁定带有 processNum = 1 的行,这将阻止其他事务修改行直到您完成事务。

您可以在此处详细了解 SQL 服务器如何为不同的隔离级别放置锁:SET TRANSACTION ISOLATION LEVEL

在您之前对问题的编辑中,您还想知道在 Oracle 数据库中是如何处理这个问题的。这很简单:无论您使用哪种隔离级别,读者 永远不会 阻止写入者,因此 select 查询永远不会阻止其他事务修改行。