事务内的FOR UPDATE不会锁定行

San*_*ira 1 .net c# 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();
Run Code Online (Sandbox Code Playgroud)

我得到的结果是:

Enter t1: True
Enter t2: 8534
Exit t2
Exit t1
Run Code Online (Sandbox Code Playgroud)

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

Qua*_*noi 5

FOR UPDATE在线程1中是否应该阻止线程2在释放事务之前读取该行?

没有.

但它会阻止线程2写入此行(或者也可以使用FOR UPDATE子句读取它).

在默认事务隔离级别(即REPEATABLE READ)中,SELECT语句不会对它们读取的行放置任何锁定.

对于SELECT语句来锁定你应该指示它锁(通过使用FOR UPDATE,LOCK IN SHARE MODE或将读取的事务隔离级别SERIALIZABLE).

来自文档:

一致性读取是InnoDB进程SELECT语句READ COMMITTEDREPEATABLE READ隔离级别的默认模式.一致读取不会对其访问的表设置任何锁定,因此其他会话可以在对表执行一致读取的同时自由修改这些表.

InnoDB对select子句使用一致读取INSERT INTO ... SELECT, UPDATE ... (SELECT),并且CREATE TABLE ... SELECT不指定FOR UPDATE或者LOCK IN SHARE MODE是否innodb_locks_unsafe_for_binlog设置了选项,并且事务的隔离级别未设置为SERIALIZABLE.因此,在从所选表读取的行上没有设置锁.否则,InnoDB使用更强的锁定,SELECT部分就像READ COMMITTED,每个一致的读取,即使在同一个事务中,也会设置和读取自己的新快照.