为什么$dbh->disconnect
会导致自动递增列出现间隙?
use DBI;
my $db = 'MYDB2';
my $table = 'SCHEMA.TABLE';
my $user = 'user';
my $pass = 'passwd';
my $dsn = "dbi:DB2:$db";
my $dbh = DBI->connect( $dsn, $user, $pass );
$dbh->do( "DROP TABLE IF EXISTS $table" );
$dbh->do( "CREATE TABLE $table (ID INT NOT NULL GENERATED ALWAYS AS IDENTITY PRIMARY KEY, NAME CHAR(3))" );
my $sth = $dbh->prepare( "INSERT INTO $table (NAME) VALUES(?)" );
$sth->execute( 'aaa' );
$sth->execute( 'bbb' );
$sth = $dbh->prepare( "SELECT * FROM $table" );
$sth->execute();
$sth->dump_results;
$sth->finish;
$dbh->disconnect;
$dbh = DBI->connect( $dsn, $user, $pass );
$sth = $dbh->prepare( "INSERT INTO $table (NAME) VALUES(?)" );
$sth->execute( 'ccc' );
$sth->execute( 'ddd' );
$sth = $dbh->prepare( "SELECT * FROM $table" );
$sth->execute();
$sth->dump_results;
'1', 'aaa'
'2', 'bbb'
2 rows
'1', 'aaa'
'2', 'bbb'
'21', 'ccc'
'22', 'ddd'
4 rows
如果不使用disconnect
,则创建的自动增量列没有间隙:
一个二个一个一个
3条答案
按热度按时间v2g6jxz61#
这是按设计工作的,IDENTITY列GENERATED ALWAYS不保证是连续的,应该预料到间隙。
这与Perl或DBD:DB2无关,这只是Db2实现总是生成的标识列的方式。Db2在内部为每个连接的此类列维护一个标识值的小缓存,在使用值的事务回滚后、崩溃或异常终止后、其他应用程序(其他连接)将值插入同一标识列或增量/减量值不为1时,您可能会得到间隙。
尽管在指定标识列时可以使用“NO CACHE”选项,或者指定较低的缓存值,但出于性能/并发性原因,这些选项是不可取的。
如果您想强制实现零间隙,则必须使用不同的技术,这通常会对高插入频率的应用程序和/或可伸缩性/并发性挑战带来性能影响。
57hvy0tb2#
您可以对标识列该高速缓存选项进行更改。基本上,出于性能原因,会缓存和使用大量标识,以避免同步。您可以减少差距,但可能会降低性能。
41ik7eoe3#
原因是,数据库很可能在应用程序会话断开时被停用,因为它是唯一使用数据库的应用程序。
停用数据库时,所有未使用的序列缓存值都将丢失。
您可以使用
ACTIVATE DATABASE
命令避免隐式数据库激活/去激活,但它无法帮助您避免回滚和示例重新启动时的间隙。