我进行此测试是为了从两个线程中选择我之前创建的一行:
CREATE TABLE `customers` (
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`),
) ENGINE=InnoDB
var t1 = new Thread(new ThreadStart(delegate()
{
using (var conn = new MySqlConnection("Server=localhost;Database=test;Uid=root;Pwd=test;"))
{
conn.Open();
using (var trans = conn.BeginTransaction())
{
using (var cmd = new MySqlCommand("select id from customers where id = 8534 FOR UPDATE;", conn, trans))
{
using (var reader = cmd.ExecuteReader())
{
Console.WriteLine("Enter t1: " + reader.Read());
Thread.Sleep(2000);
Console.WriteLine("Exit t1");
}
}
}
};
}));
var t2 = new Thread(new ThreadStart(delegate()
{
using (var conn = new MySqlConnection("Server=localhost;Database=test;Uid=root;Pwd=test;"))
{
conn.Open();
using (var cmd = new MySqlCommand("select id from customers where id = 8534", conn))
{
Console.WriteLine("Enter t2: " + cmd.ExecuteScalar());
Console.WriteLine("Exit t2");
}
}
}));
t1.Start();
Thread.Sleep(400);
t2.Start();
t1.Join();
t2.Join();
我得到的结果是:
Enter t1: True
Enter t2: 8534
Exit t2
Exit t1
线程 1 中的 FOR UPDATE 是否应该阻止线程 2 读取行直到它释放事务?
最佳答案
Shouldn't the
FOR UPDATE
in thread 1 prevent thread 2 to read the row until it releases the transaction?
没有。
但它会阻止线程 2 写入此行(或使用 FOR UPDATE
子句读取它)。
在默认事务隔离级别(即 REPEATABLE READ
)中,SELECT
语句不会在它们读取的行上放置任何锁。
要锁定 SELECT
语句,您应该指示它锁定(通过使用 FOR UPDATE
、LOCK IN SHARE MODE
或设置读者的事务隔离级别为 SERIALIZABLE
)。
来自docs :
Consistent read is the default mode in which
InnoDB
processesSELECT
statements inREAD COMMITTED
andREPEATABLE READ
isolation levels. A consistent read does not set any locks on the tables it accesses, and therefore other sessions are free to modify those tables at the same time a consistent read is being performed on the table.
和
InnoDB
uses a consistent read for select in clauses likeINSERT INTO ... SELECT, UPDATE ... (SELECT)
, andCREATE TABLE ... SELECT
that do not specifyFOR UPDATE
orLOCK IN SHARE MODE
if theinnodb_locks_unsafe_for_binlog
option is set and the isolation level of the transaction is not set toSERIALIZABLE
. Thus, no locks are set on rows read from the selected table. Otherwise, InnoDB uses stronger locks and theSELECT
part acts likeREAD COMMITTED
, where each consistent read, even within the same transaction, sets and reads its own fresh snapshot.
关于c# - 事务内的 FOR UPDATE 不锁定行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4794087/