PHP Telnet获取ONT数据插入MySQL触发PDO 1062重复键错误求助
错误原因定位
错误SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1' for key 'UC_cdata_ont_info'明确指向:插入的记录触发了UC_cdata_ont_info唯一键约束,新记录中该唯一键对应的字段值已在表中存在。
前两条命令正常、第三条及之后报错,大概率是以下情况之一:
- 第三条及后续Telnet命令返回了重复的ONT数据(比如重复查询同一个PON口的ONT)
- 解析逻辑存在缺陷,第三条及之后的返回数据被错误解析,生成了重复的唯一键值(比如所有记录的某个字段被固定解析为
1) - 代码仅做插入操作,未处理“记录已存在”的场景
排查步骤
确认唯一键结构
执行SQL命令查看表的唯一键定义:SHOW CREATE TABLE cdata_ont_info;找到
UC_cdata_ont_info对应的字段(可能是单个字段如ont_id,也可能是联合字段如olt_ip + pon_port + ont_id),明确哪些字段的组合不能重复。校验解析后的数据
在代码中添加日志或打印逻辑,输出每条Telnet命令返回的原始数据,以及解析后对应唯一键字段的取值。重点检查第三条及之后的数据:- 是否存在与前两条重复的唯一键值?
- 是否出现大量取值为
1的唯一键字段(对应错误中的Duplicate entry '1')?如果是,说明解析逻辑在处理第三条命令的返回数据时失效。
检查Telnet命令范围
核对第三条及后续的Telnet查询命令,确认是否查询了已处理过的ONT资源(比如重复查询同一个PON口、同一批ONT),导致重复获取相同的ONT信息。
解决方法
1. 改用“插入或更新”语法(推荐)
利用MySQL的INSERT ... ON DUPLICATE KEY UPDATE语法,当遇到唯一键冲突时自动更新现有记录,而非报错:
// 示例:假设唯一键是ont_id,根据实际字段调整 $sql = "INSERT INTO cdata_ont_info (ont_id, olt_ip, pon_port, ont_name, status) VALUES (:ont_id, :olt_ip, :pon_port, :ont_name, :status) ON DUPLICATE KEY UPDATE olt_ip = VALUES(olt_ip), pon_port = VALUES(pon_port), ont_name = VALUES(ont_name), status = VALUES(status)"; $stmt = $pdo->prepare($sql); $stmt->execute([ ':ont_id' => $parsedOntId, ':olt_ip' => $oltIp, ':pon_port' => $ponPort, ':ont_name' => $ontName, ':status' => $ontStatus ]);
2. 先查询再执行对应操作
如果不想使用ON DUPLICATE KEY UPDATE,可以先判断记录是否存在,再执行插入或更新:
// 假设唯一键是ont_id $checkStmt = $pdo->prepare("SELECT 1 FROM cdata_ont_info WHERE ont_id = :ont_id"); $checkStmt->execute([':ont_id' => $parsedOntId]); if ($checkStmt->rowCount() > 0) { // 记录存在,执行更新 $updateStmt = $pdo->prepare("UPDATE cdata_ont_info SET olt_ip = :olt_ip, pon_port = :pon_port WHERE ont_id = :ont_id"); $updateStmt->execute([ ':olt_ip' => $oltIp, ':pon_port' => $ponPort, ':ont_id' => $parsedOntId ]); } else { // 记录不存在,执行插入 $insertStmt = $pdo->prepare("INSERT INTO cdata_ont_info (ont_id, olt_ip, pon_port) VALUES (:ont_id, :olt_ip, :pon_port)"); $insertStmt->execute([ ':ont_id' => $parsedOntId, ':olt_ip' => $oltIp, ':pon_port' => $ponPort ]); }
3. 修正解析逻辑
如果排查发现是解析错误导致重复生成1这类固定值,需要针对性修复解析代码:
- 检查正则表达式是否匹配第三条命令返回的文本格式(比如返回的字段分隔符、位置是否变化)
- 确认字符串分割、取值逻辑是否有边界处理(比如空值、异常格式的 fallback 逻辑是否合理)
4. 调整Telnet命令范围
如果是命令重复查询导致重复数据,修改Telnet命令的查询参数,确保每条命令对应不同的ONT资源(比如按PON口、ONT ID范围分批查询)。
额外注意事项
- 确保唯一键的设计符合业务逻辑:比如ONT的唯一标识应该是
OLT IP + PON口 + ONT ID的组合,此时应设置联合唯一键,避免不同OLT下的ONT ID重复导致冲突。 - 开启PDO异常模式便于调试:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
内容的提问来源于stack exchange,提问作者0p3nS0urc3 2015

