我有一个脚本,可以运行多年备份中的数百甚至数千个表,以更改人们要求的内容。
从本月开始,它开始使用过多的 RAM,以至于服务器杀死了它。
那么,有没有一种方法可以在每次从数据库中提取数据并让我的 Perl 脚本运行数据、搜索要更改的信息后,在提取下一个数据之前重置 RAM?
所以基本上它会重置刚刚提取的数据,以便所有这些数据都不在 RAM 中?
我在 2007 年创建了这个东西,我当然希望我做得方式有所不同,但这需要进行重大修改和更新,而我现在无法做到这一点。也许在将来。但到目前为止,我还不能这样做。
所以我需要一种方法来防止这种情况发生。
如果您知道清除该内存的方法,请告诉我。
如果您能给我指路,请先谢谢您。
--- 更新 ---- 添加了实际拉取所有数据的部分网站代码 ----
$_startingTime = time();
$dbh->do(qq{update `tun_changes` set `status` = "working", `startedT` = ? where `unid` = ?}, undef, $_startingTime, $_tr->{unid});
$sth2 = $dbh->prepare(qq{select * from `allmembers` where `mId` = ?});
$sth2->execute($_tr->{mId});
$_tregmem = $sth2->fetchrow_hashref();
$sth2->finish();
$dbh->do(qq{delete from `sessions` where `id` = "$_tregmem->{last_sessid}"}); #kill their logged in session, so it does not lock them up if they are logged in when we change their username...
$_un = $_tregmem->{tusername};
$_cust_id = $_tr->{mId};
$_notfinished = 0;
$_newUname = lc($_tr->{newun});
$_csusername = $_tr->{csusername};# if customer service rep...
$_count = 0;
$_changeFailed = 0;
$_changed = 0;
$_debugChg = 1;
if($_debugChg) {
open(DBG,">>/home$_website_username/required/files/urgent/all_chg_uname_debug_track.txt");
seek(DBG,0,2);
print DBG "Checking Table at " . Format_Date_For_Viewing($_startingTime,"") . " - indented two lines at least for this record.... until _end_ is shown\n";
}
@_mb = $dbh->tables;
$_tablesAffected = 0;
foreach $_k (@_mb) {
$_sql = "select * from $_k";
if($_debugChg) {
print DBG "\tTable $_k (" . duration(time() - $_startingTime) . " into action)\n";
}
$sth2 = $dbh->prepare($_sql);
$sth2->execute();
@_mb2 = @{$sth2->{NAME}};
foreach $_k2 (@_mb2) {
if($_debugChg) {
print DBG "\t\tColumn $_k2";
}
if($_k2 =~ /tusername/i) {
if($_debugChg) {
print DBG "\t Checking for username entries in $_k2\n";
}
$_updated = $dbh->do(qq{update $_k SET `$_k2` = ? WHERE `$_k2` = ?}, undef, $_newUname, $_un);
if($_updated) {
$_changed += $_updated;
} else {
$_changeFailed += $_updated;
}
} else {
if($_debugChg) {
print DBG " - Not UN\n";
}
}
}
$sth2->finish();
if($_debugChg) {
print DBG "\n";
}
}
if($_debugChg) {
print DBG "\nFinished - Duration was: " . duration(time() - $_startingTime) . "\n";
print DBG "\n_end_\n\n";
close(DBG);
}
我留下了调试代码,以便在出现故障时可以看到做了什么。
最佳答案
这里的问题并不明显。看起来并不存在明显的内存泄漏,因此尝试释放分配的内存可能不是您需要解决的问题。理论上,Perl 可以在运行时将内存释放回操作系统,但必须满足某些条件,并且根据我的经验,这种情况并不常见。
连接到数据库后设置$dbh->{mysql_use_result} = 1;
可能会有很大帮助。
这改变了 DBI(实际上是 libmysqlclient)从套接字读取传入数据的方式,导致每次调用 fetchrow* 方法时它都会根据需要读取数据,而不是先将其全部缓冲到内存中,然后一次从内存中已有的内容中向您提供一行,这是默认行为。
DBD::mysql
和底层库可能是负责大量内存使用的实体,因此值得一试。
关于mysql - 在进程中间从脚本中释放内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37106211/