c# - 事务内的 FOR UPDATE 不锁定行

标签 c# .net mysql locking

我进行此测试是为了从两个线程中选择我之前创建的一行:

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 UPDATELOCK IN SHARE MODE 或设置读者的事务隔离级别为 SERIALIZABLE)。

来自docs :

Consistent read is the default mode in which InnoDB processes SELECT statements in READ COMMITTED and REPEATABLE 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 like INSERT INTO ... SELECT, UPDATE ... (SELECT), and CREATE TABLE ... SELECT that do not specify FOR UPDATE or LOCK IN SHARE MODE if the innodb_locks_unsafe_for_binlog option is set and the isolation level of the transaction is not set to SERIALIZABLE. Thus, no locks are set on rows read from the selected table. Otherwise, InnoDB uses stronger locks and the SELECT part acts like READ 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/

相关文章:

php - mysqli_multi_query 不返回任何值

c# - 使用 R.Net 从 R 评估中检索结果

c# - WPF:使用不透明蒙版作为背景的图像

.net - 奇怪的反序列化错误,子对象没有完全反序列化

c# - 如何在 C# 中为测量单位创建通用转换器?

MySQL子查询中的COUNT非常慢

c# - 具有工作线程的 WCF 服务?

c# - 在发送到服务器之前更改 Webbrowser 发布表单

c# - Visual Studio 2010 - 无法单步执行 .NET Framework 4 源 (PresentationCore.dll)

PHP登录并连接到MySql