You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多RSS条目插入MySQL数据库异常问题排查求助

问题排查与解决方案

核心原因

你的脚本仅插入每个Feed的1条条目,核心问题出在数据库表约束与插入逻辑不匹配:
你在插入时将Feed的标识ID(即每个资源的id字段)赋值给了数据库表的id字段,如果articles表的id是主键或设置了唯一约束,同一个Feed的所有条目都会因为id重复而插入失败,最终只能成功插入每个Feed的第一条数据。

另外脚本还存在两个次要问题:

  1. 插入循环固定执行1000次,若$data数组实际条目数不足1000,会触发数组越界错误导致脚本终止;
  2. 未检查数据库插入的执行结果,无法及时发现插入失败的具体原因。

解决方案

1. 修正数据库表结构

如果id字段是主键,建议将其改为自增主键,同时新增feed_id字段存储Feed的标识(即原脚本中的$resource['id']),避免主键冲突。
示例SQL修改:

ALTER TABLE articles MODIFY COLUMN id INT AUTO_INCREMENT PRIMARY KEY;
ALTER TABLE articles ADD COLUMN feed_id INT NOT NULL;

2. 调整插入逻辑

  • 修改SQL语句,将原id字段替换为新增的feed_id;
  • 根据$data的实际长度循环插入,避免数组越界;
  • 添加执行结果检查,记录错误信息方便排查。

3. 优化脚本细节

  • 变量名$json改为$xmlDoc,避免混淆(因为加载的是RSS XML而非JSON);
  • 每次加载新RSS时创建新的DOMDocument实例,避免残留数据;
  • 优化预处理语句的使用,减少重复绑定的开销。

修改后的完整脚本

<?php
$data = array();

$resources = array(
    array( 'type' => 'Article', 'source' => 'Source 1', 'feedurl' => 'http://www.example1.com/feed/', 'id' => '1' ),
    array( 'type' => 'Article', 'source' => 'Source 2', 'feedurl' => 'https://example2.com/feed', 'id' => '2' ),
    array( 'type' => 'Article', 'source' => 'Source 3', 'feedurl' => 'https://example3.com/feed', 'id' => '3' )
);

foreach ( $resources as $resource ) {
  // 每次循环创建新的DOMDocument实例
  $xmlDoc = new DOMDocument();
  // 禁用错误输出,避免RSS格式问题导致脚本终止
  libxml_use_internal_errors(true);
  $loadSuccess = $xmlDoc->load( $resource['feedurl'] );
  libxml_clear_errors();
  
  if (!$loadSuccess) {
      // 记录Feed加载失败的信息
      error_log("Failed to load feed: " . $resource['feedurl']);
      continue;
  }

  foreach ( $xmlDoc->getElementsByTagName( 'item' ) as $node ) {
    // 检查节点是否存在必要字段,避免报错
    $titleNode = $node->getElementsByTagName( 'title' )->item( 0 );
    $linkNode = $node->getElementsByTagName( 'link' )->item( 0 );
    $dateNode = $node->getElementsByTagName( 'pubDate' )->item( 0 );
    
    if (!$titleNode || !$linkNode || !$dateNode) {
        continue;
    }

    $item = array(
      'source'  => $resource['source'],
      'type'    => $resource['type'],
      'title'   => $titleNode->nodeValue,
      'link'    => $linkNode->nodeValue,
      'date'    => $dateNode->nodeValue,
      'feed_id' => $resource['id']
    );

    array_push( $data, $item );
  }
}

// 按日期排序
usort( $data, function( $a, $b ) {
  return strtotime( $b['date'] ) - strtotime( $a['date'] );
});

// 数据库连接
$servername = '???';
$username = '???';
$password = '???';
$dbname = '???';

$DBconnection = new mysqli($servername, $username, $password, $dbname);
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

// 调整SQL语句,使用feed_id替代原id字段
$sql = "INSERT INTO articles(source, type, title, url, date, feed_id) VALUES(?, ?, ?, ?, ?, ?)";
$stmt = $DBconnection->prepare($sql);
if (!$stmt) {
    error_log("Prepare failed: " . $DBconnection->error);
    $DBconnection->close();
    exit();
}

// 绑定参数(仅绑定一次)
$source = '';
$type = '';
$title = '';
$link = '';
$date = '';
$feed_id = 0;
$stmt->bind_param("sssssi", $source, $type, $title, $link, $date, $feed_id);

// 计算实际要插入的条目数(最多1000条)
$insertCount = min(count($data), 1000);

for ( $x = 0; $x < $insertCount; $x++ ) {
    $source = $data[ $x ]['source'];
    $type = $data[ $x ]['type'];
    $title = htmlspecialchars(str_replace( ' & ', ' &amp; ', $data[ $x ]['title'] ));
    $link = htmlspecialchars($data[ $x ]['link']);
    $date = date( 'Y-m-d H:i:s', strtotime( $data[ $x ]['date'] ) );
    $feed_id = $data[ $x ]['feed_id'];

    if (!$stmt->execute()) {
        // 记录插入失败的信息
        error_log("Insert failed for item $x: " . $stmt->error);
    }
}

$stmt->close();
$DBconnection->close();
?>

额外建议

  • 可以给url字段添加唯一约束,避免插入重复的文章条目;
  • 考虑使用批量插入(如INSERT INTO ... VALUES (...), (...), ...)来提高插入效率,减少数据库交互次数;
  • 增加脚本超时时间(如set_time_limit(300);),避免处理大量Feed时超时。

内容的提问来源于stack exchange,提问作者Damage

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 01:50:25