事务下的 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 read
或 serializable
模式,那么是的,执行 select
查询将锁定带有 processNum = 1
的行,这将阻止其他事务修改行直到您完成事务。
您可以在此处详细了解 SQL 服务器如何为不同的隔离级别放置锁:SET TRANSACTION ISOLATION LEVEL。
在您之前对问题的编辑中,您还想知道在 Oracle 数据库中是如何处理这个问题的。这很简单:无论您使用哪种隔离级别,读者 永远不会 阻止写入者,因此 select
查询永远不会阻止其他事务修改行。
我们有这段代码,我想知道,在正常的 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 read
或 serializable
模式,那么是的,执行 select
查询将锁定带有 processNum = 1
的行,这将阻止其他事务修改行直到您完成事务。
您可以在此处详细了解 SQL 服务器如何为不同的隔离级别放置锁:SET TRANSACTION ISOLATION LEVEL。
在您之前对问题的编辑中,您还想知道在 Oracle 数据库中是如何处理这个问题的。这很简单:无论您使用哪种隔离级别,读者 永远不会 阻止写入者,因此 select
查询永远不会阻止其他事务修改行。