Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 为什么SELECT FOR UPDATE仅在事务中起作用?_Mysql_Perl_Transactions_Locking_Innodb - Fatal编程技术网

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

Mysql 为什么SELECT FOR UPDATE仅在事务中起作用?,mysql,perl,transactions,locking,innodb,Mysql,Perl,Transactions,Locking,Innodb,我想我对这个结构感到困惑。 例如: mysql> select * from employees2; +-------+----------+--------+-----------+ | EmpId | EmpName | DeptId | EmpSalary | +-------+----------+--------+-----------+ | 1 | John | 1 | 5000.00 | | 2 | Albert

我想我对这个结构感到困惑。
例如:

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)  
我在脚本中执行以下操作:

#!/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;  
我还可以并行使用控制台并连接到数据库。
因此,我首先运行脚本,然后在另一个会话中执行以下操作:

mysql> select * from employees2 where EmpId IN (10) for update;   
第二个选择块指的是同一行。
这将阻止我执行以下操作:

mysql> set autocommit = 0; 
mysql> begin;   
mysql> select * from employees2 where EmpId IN (10) for update;   
mysql> commit;     
或者只是

mysql> select * from employees2 where EmpId IN (10) for update;   
因此,如果它在事务中或不在事务中,它将阻止不相关的操作。
现在,如果我将脚本更改为:

my $dbh = DBI->connect('dbi:mysql:practice','root','') or die "Connection Error: $DBI::errstr\n";  
也就是说,脚本不会在第二个会话未阻止的事务中运行
如果脚本在事务中运行,为什么它只阻止

仅当禁用自动提交时(通过使用
START transaction
开始事务或将autocommit设置为0),使用
SELECT for update
锁定要更新的行。如果启用了autocommit,则与规范匹配的行不会被锁定


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

要回答您的新问题:
SELECT…FOR UPDATE
仅锁定行,直到您提交执行它的事务。
autocommit
在默认情况下处于启用状态,因此当您没有明确禁用时在这种情况下,您执行的每个SQL语句都形成一个单独的事务(即使用InnoDB)。换句话说,您的第一个
SELECT…FOR UPDATE
将被执行,然后立即提交,释放锁。@ThisSuitesBlacknot:啊,是的!将其作为答案发布,我会接受。我的评论有点偏离…至少对于MySQL 5.5,如果您在事务中不执行
SELECT FOR UPDATE
,则不会锁定hap笔(与我在评论中所说的锁定、立即提交和释放锁定相反)。顺便问一下,您是否发现了最初发布的问题,即您在
in
子句中未包含的行上看到锁?@ThisSuitesBlacknot:是的。原因是表没有定义主键。如果它是单个查询,但for update是update查询的子查询的一部分,该怎么办假设查询只有一个,并且不在事务中,但我想它应该可以工作,因为提交只在update语句之后完成。它是具有for update语句的select子查询的父查询