我有一个使用数据库表作为缓冲区的脚本。
它首先从另一个表中提取对象列表,然后运行一个为每个对象调用API的循环。对于每个API答案,我使用当前迭代对象的密钥和相应的数据以及该对象的密钥的删除语句在缓冲表中创建一个insert语句。然后我首先运行一个删除操作,从表中取出该对象的记录,然后插入新的和新的数据。
大约每5分钟发生一次,脚本运行大约2分钟。问题I我遇到了从表中删除所有元素的问题。我用R studio检查了数据,它每5分钟就会波动一次。
由于它删除了每个对象的调用,如果此删除导致了该问题,该表将一直为空。如果一切顺序运行。
以下是运行单个对象调用的函数:
function singleProp( $pId , $wispId , $nasId , $req){
$res_j = apiCall( $wispId , $nasId );
$count = get_value_by_tag($res_j , "COUNT" );
$aps = array();
$no_down = 0;
$db_con = new db_connector();
$db_con->connect();
$stmt_d = $db_con->dblink->prepare( "DELETE FROM ap_down WHERE prop_id = ? ;" );
$stmt_d->bind_param("i",$pId);
$stmt_d->execute();
$stmt_i = $db_con->dblink->prepare("INSERT INTO ap_down ( prop_id , ip , prop_type , description , time ) VALUES (?,?,?,?,now());");
for( $i = 1 ; $i <= $count ; $i++ ){
if( get_value_by_tag($res_j , "APSTATUS" , $i ) == "DOWN" ){
$stmt_i->bind_param("issd" , $pId , get_value_by_tag( $res_j , "ACCESSPOINTS" , $i ) , $req , get_value_by_tag( $res_j , "DESCRIPTION" , $i ) );
$stmt_i->execute();
$no_down ++ ;
}
}
}
您可能希望看到的任何想法,建议和其他数据?
编辑:使用预备语句,因为它更安全,更容易阅读。 编辑:代码缩进....因为重要。
答案 0 :(得分:0)
您的INSERT
声明中可能有错误,但您没有抓到。除非你enabled exception reporting,否则你可能会错过这些。
您可以找到以下帮助之一:
1。使用INSERT INTO
和ON DUPLICATE KEY
替换现有记录,而不是每次都删除它。这需要prop_id
上的唯一索引,但您应该已经根据您使用该表的方式确定了索引。
2. 使用REPLACE INTO
完全重写记录。
3。创建一个事务来封装DELETE
和INSERT
操作,以便它是一个全有或全无的情况而且你是没有留下不完整的更新。
答案 1 :(得分:0)
您的问题似乎是对ap_down
表的并发访问之一。你应该确保所有操作都与其他操作隔离开来。
阅读过程:
LOCK TABLES ap_down READ;
SELECT ...;
UNLOCK TABLES;
写入过程(您的脚本):
LOCK TABLES ap_down WRITE;
DELETE ...;
INSERT ...;
UNLOCK TABLES;
您可以采用不同的方式执行写入过程,以便仅在插入时锁定,并在锁定后立即删除:
// Do not lock -- yet.
$stmt_d = $db_con->dblink->prepare( "DELETE FROM ap_down WHERE prop_id = ? ;" );
$stmt_d->bind_param("i",$pId);
// Do not execute deletion -- yet.
$deleted = false;
$stmt_i = $db_con->dblink->prepare("INSERT INTO ap_down ( prop_id , ip , prop_type , description , time ) VALUES (?,?,?,?,now());");
for( $i = 1 ; $i <= $count ; $i++ ){
if ( get_value_by_tag($res_j , 'APSTATUS', $i ) != 'DOWN' ){
continue;
}
$db_con->dblink->query('LOCK TABLES ap_down WRITE;');
if (!$deleted) {
$deleted = true;
$stmt_d->execute();
}
$stmt_i->bind_param('issd', $pId, get_value_by_tag( $res_j, 'ACCESSPOINTS', $i ), $req , get_value_by_tag( $res_j, 'DESCRIPTION', $i ) );
$stmt_i->execute();
$db_con->dblink->query('UNLOCK TABLES;');
$no_down ++ ;
}
if (!$deleted) {
// Delete without locking.
$deleted = true;
$stmt_d->execute();
}