我认为我对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)
我在脚本中执行以下操作:
#!/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";
即脚本在第二个会话未阻止的事务中不运行! 如果脚本在事务中运行,为什么它只阻止 ?
答案 0 :(得分:9)
使用
SELECT FOR UPDATE
锁定行以进行更新仅适用于禁用自动提交时(通过使用START TRANSACTION
开始事务或将自动提交设置为0.如果启用了自动提交,则与规范不匹配的行不会锁定。
换句话说,如果您未在交易中执行第一个SELECT FOR UPDATE
,则不会锁定任何行。