3

我有将行同时插入表A 的应用程序。每个应用程序以批处理模式插入行(使用 JDBC 准备语句),每个批处理使用一个事务(以避免在每个 之后重建索引INSERT)。每个批次中存在的行是完全独立的,事务仅用于优化。每个插入的行都会自动设置其主键 ( AUTO_INCREMENT)。

我有另一个应用程序根据它们的 ID 处理表 A 中的行。应用程序处理 range [ID1,ID2],然后处理 range [ID2+1,ID3][ID3+1,ID4]依此类推。每个范围,例如,[ID1,ID2]可能包含在不同事务期间插入的行,并且可能其中一些事务可能尚未提交。例如,在 range 中[ID1,ID2],行[ID1,ID1+N]可能已在尚未提交的事务期间插入,而行[ID1+N+1,ID2]可能已在已提交的事务期间插入。因此,当在范围内选择行时[ID1,ID2],交易隔离级别设置为READ_UNCOMMITTED以使得不合规行可见。

问题是有时,未提交的行是不可见的,因此永远不会被处理。

SELECT当 s在 s 之后很短的时间内执行时,似乎会出现该问题INSERT。我做了一个测试,其中一个连接在批处理中插入多行包装为事务,并且在提交事务之前,等待一段时间后,另一个连接READ_UNCOMMITTED以事务隔离级别查询行,并且这些行是可见的。因此,我得出的结论是,即使插入了一行并且释放了自增计数器锁,尽管READ_UNCOMMITTED设置为事务隔离级别,但该行可能对其他事务不可见。

4

1 回答 1

0

如果我从另一个控制台登录,使用我的小测试脚本在提交之前不会显示任何记录。不过,我可以在同一个会话中选择刚刚插入的记录。因此,我假设在提交之前您可能会访问表中已经存在的行,但现在是新行或在提交之前进行的更改。

<?php

require_once('db.php');

q( 'drop table if exists t' );
q( 'create table t (id integer not null auto_increment primary key, v datetime) engine=innodb' );

q( 'set transaction isolation level read uncommitted' );
q( 'start transaction' );
q( 'insert into t (v) values (now()),(now()),(now())' );

echo q1( 'count(*)', 't', 'true'); // translates to "select count(*) from t where true"; 
// echoes "3" to the console

// wait for input
$handle = fopen ("php://stdin","r");
$line = fgets($handle);

// with a mysql client from a 2nd console at this point no new records show in table t

q( 'commit' );

// after this point all new records show up in table t from a 2nd session.
于 2014-06-17T12:41:23.543 回答