为什么SELECT FOR UPDATE仅在事务中起作用?

Cra*_*lus 3 mysql perl innodb locking transactions

我认为我对SELECT FOR UPDATE构造感到困惑.
例:

mysql> select * from employees2;  
+-------+----------+--------+-----------+  
| EmpId | EmpName  | DeptId | EmpSalary |  
+-------+----------+--------+-----------+  
|     1 | John     |      1 |   5000.00 |  
|     2 | Albert   |      1 |   4500.00 |  
|     3 | Crain    |      2 |   6000.00 |  
|     4 | Micheal  |      2 |   5000.00 |  
|     5 | David    |   NULL |     34.00 |  
|     6 | Kelly    |   NULL |    457.00 |  
|     7 | Rudy     |      1 |    879.00 |  
|     8 | Smith    |      2 |   7878.00 |  
|     9 | Karsen   |      5 |    878.00 |  
|    10 | Stringer |      5 |    345.00 |  
|    11 | Cheryl   |   NULL |      NULL |  
+-------+----------+--------+-----------+  
11 rows in set (0.00 sec)  
Run Code Online (Sandbox Code Playgroud)

我在脚本中执行以下操作:

#!/usr/bin/perl  
use strict;  
use warnings;  

use DBI;  

my $dbh = DBI->connect('dbi:mysql:testdb','root','1234', {'RaiseError' => 1, 'AutoCommit' => 0}) or die "Connection Error: $DBI::errstr\n";  
my $sql = "select * from employees2 where EmpId IN (2,10) for update";   
my  $sth = $dbh->prepare($sql);  
$sth->execute or die "SQL Error: $DBI::errstr\n";  
while (my @row = $sth->fetchrow_array) {  
   print "@row\n";  
}   
sleep(9000);  
$dbh->commit;  
Run Code Online (Sandbox Code Playgroud)

我还并行控制台并连接到数据库.
所以我首先运行脚本,然后在另一个会话中执行:

mysql> select * from employees2 where EmpId IN (10) for update;   
Run Code Online (Sandbox Code Playgroud)

第二个选择块指向同一行.
这阻止我做:

mysql> set autocommit = 0; 
mysql> begin;   
mysql> select * from employees2 where EmpId IN (10) for update;   
mysql> commit;     
Run Code Online (Sandbox Code Playgroud)

要不就

mysql> select * from employees2 where EmpId IN (10) for update;   
Run Code Online (Sandbox Code Playgroud)

因此,如果它在交易中,它就会阻止无关紧要.
现在,如果我将脚本更改为:

my $dbh = DBI->connect('dbi:mysql:practice','root','') or die "Connection Error: $DBI::errstr\n";  
Run Code Online (Sandbox Code Playgroud)

即脚本不在事务中运行,第二个会话不会阻塞!
为什么在脚本在事务中运行时才会阻塞?

Thi*_*Not 11

根据文件:

锁定行以进行更新SELECT FOR UPDATE仅适用于禁用自动提交时(通过启动事务START TRANSACTION或通过将自动提交设置为0.如果启用了自动提交,则不会锁定与规范匹配的行.

换句话说,如果您没有SELECT FOR UPDATE在事务中执行第一个,则不会锁定任何行.