C# 对于事务内的更新,不会锁定行

C# 对于事务内的更新,不会锁定行,c#,.net,mysql,locking,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=l

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

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在释放事务之前读取该行吗

线程1中的FOR UPDATE不应该阻止线程2在释放事务之前读取该行吗

没有

但它会阻止线程2写入这一行或用FORUPDATE子句读取这一行

在可重复读取的默认事务隔离级别中,SELECT语句不会对其读取的行放置任何锁

对于要锁定的SELECT语句,您应该通过使用For UPDATE、在共享模式下锁定或将读取器的事务隔离级别设置为SERIALIZABLE来指示它锁定

从:

一致读取是默认模式,InnoDB处理读取提交和可重复读取隔离级别中的SELECT语句。一致读取不会对其访问的表设置任何锁,因此其他会话可以在对表执行一致读取的同时自由修改这些表

InnoDB对select in子句(如INSERT INTO。。。选择,更新。。。选择,然后创建表。。。如果设置了innodb_locks_unsafe_FOR_binlog选项且事务的隔离级别未设置为SERIALIZABLE,则选择不指定在共享模式下更新或锁定。因此,不会对从所选表读取的行设置锁。否则,InnoDB将使用更强的锁,选择部分的行为类似于READ COMMITTED,其中每个一致读取(即使在同一事务中)都会设置并读取自己的新快照

线程1中的FOR UPDATE不应该阻止线程2在释放事务之前读取该行吗

没有

但它会阻止线程2写入这一行或用FORUPDATE子句读取这一行

在可重复读取的默认事务隔离级别中,SELECT语句不会对其读取的行放置任何锁

对于要锁定的SELECT语句,您应该通过使用For UPDATE、在共享模式下锁定或将读取器的事务隔离级别设置为SERIALIZABLE来指示它锁定

从:

一致读取是默认模式,InnoDB处理读取提交和可重复读取隔离级别中的SELECT语句。一致读取不会对其访问的表设置任何锁,因此其他会话可以在对表执行一致读取的同时自由修改这些表

InnoDB对select in子句(如INSERT INTO。。。选择,更新。。。选择,然后创建表。。。如果设置了innodb_locks_unsafe_FOR_binlog选项且事务的隔离级别未设置为SERIALIZABLE,则选择不指定在共享模式下更新或锁定。因此,不会对从所选表读取的行设置锁。否则,InnoDB将使用更强的锁,选择部分的行为类似于READ COMMITTED,其中每个一致读取(即使在同一事务中)都会设置并读取自己的新快照