我正在开发一个Perl / DBI / DBD / MySQL应用程序。我使用事务级别为“可重复读”和“自动提交= 0”的InnoDB。为了保护我正在操作的数据不受其他线程或连接并发操作的影响,我使用了以下模式(这是非常常见的):
$h_DB -> do("START TRANSACTION");
$s_SQL = "SELECT data from Users where ID = ? FOR UPDATE";
$h_ST = $h_DB -> prepare($s_SQL);
$h_ST -> execute($s_ID);
# Do some other stuff
@ar_Row = $h_ST -> fetchrow_array();
# Do data manipulation
$h_DB -> do("COMMIT")为了清晰起见,我忽略了错误处理和变量声明,但我认为变量名是自我解释的。
我的问题是:何时将锁(在本例中为独占锁)放置到相应的行上?它们是在执行运行后就已经就位了,还是在获取行之后才被激活呢?换句话说,锁是否已经放置在指定的"#做一些其他事情“部分?
通常,通过使用MySQL命令行工具进行一些研究,可以很容易地回答这些问题。但在这种情况下,我认为这是不可能的,原因如下:
1)我不确定MySQL客户机的行为是否与Perl的DBI / DBD完全相同。
2)当然,上面的例子是非常简单的。实际上,我想知道在使用上面的模式时何时设置锁,但同时锁定数百行,即与WHERE子句匹配的数百行。
我不认为我可以使用命令行客户端来找出原因,因为对于大型数据集,可能存在由Perl和命令行客户端以不同方式处理的缓冲,而且我怀疑我是否能够“模拟”在Perl中执行的语句,但通过在命令行客户机中使用类似于“极限0”的方法来“模拟”其结果行。
有人能给出一个明确的答案吗?
发布于 2016-03-07 16:47:02
$s_SQL =“从ID =?进行更新的用户中选择数据”;
执行此操作将尝试获取受影响行的锁,然后获取数据(或等待直到获得所有受影响行的独占锁)。这样做是为了确保线程安全,并且只返回已经锁定的数据:这样可以保证服务器返回任何其他客户机/线程无法修改的最新数据。
行将被锁定,直到提交或回滚。
MySQL client中的行为与在服务器而不是在客户端库中执行锁定相同。
这只适用于MySQL InnoDB表。像MyISAM这样的其他引擎的行为也不同。
发布于 2016-03-07 17:42:16
而不是
$h_DB->do("START TRANSACTION");
...
$h_DB->do("COMMIT");您可能应该调用DBI方法
$h_DB->begin_work;
...
$h_DB->commit;唯一的区别是,您在自己的代码中对数据库驱动程序的行为进行事后猜测,同时降低了它的可移植性。DBI调用依赖于知道如何为该数据库启动和停止事务的驱动程序,这是正确的方法。
数据库事务的本质是事务中的所有内容都将不受任何并行数据库连接的干扰。有些数据库只需在事务期间锁定整个数据库,但大多数数据库将在事务进行期间进行优化,允许从任何地方读取和写入不相关的表。
SELECT与FOR UPDATE限定符的含义是,您要求在读取开始时启动事务,并且不需要自己显式地打开事务。一旦您获得了这些值,它们就不会被更改,数据库中任何影响它们的内容也不会被更改。需要访问您锁定的数据的连接将被挂起,除非它们要求具有脏读取功能。
这涵盖了一切吗?
https://stackoverflow.com/questions/35848981
复制相似问题