• 设为首页
  • 收藏本站
  • 积分充值
  • VIP赞助
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    福建二哥 门户 查看主题

    MySQL处理重复数据插入的处理方案

    发布者: Error | 发布时间: 2025-6-14 14:25| 查看数: 126| 评论数: 0|帖子模式

    1. 引言

    在数据库操作中,处理重复数据插入是一个常见的需求。特别是在批量插入数据时,可能会遇到主键冲突或唯一键冲突(Duplicate entry)的情况。如何优雅地捕获这类异常并执行相应的业务逻辑,是提高代码健壮性的关键。
    本文将以一个实际的Python MySQL数据库操作为例,分析如何优化异常处理逻辑,使得当出现Duplicate entry错误时,能够执行特定的业务方法(如更新记录状态)。同时,我们也会对比Java中的类似处理方式,帮助读者更好地理解不同语言下的异常处理机制。

    2. 问题背景


    2.1 原始代码分析

    原始代码的功能是批量插入手机号数据到MySQL数据库,其核心逻辑如下:
    1. def insert_into_mysql(phone_numbers, prefix, province, city):
    2.     try:
    3.         connection = get_db_connection()
    4.         cursor = connection.cursor()
    5.         
    6.         data_to_insert = []
    7.         for phone_number in phone_numbers:
    8.             if len(phone_number) == 11:
    9.                 suffix = phone_number[-4:]
    10.                 data_to_insert.append((prefix, suffix, phone_number, province, city))
    11.         
    12.         cursor.executemany(INSERT_QUERY, data_to_insert)
    13.         connection.commit()
    14.         return True
    15.    
    16.     except Exception as e:
    17.         print(f"插入数据失败: {e}")
    18.         if connection:
    19.             connection.rollback()
    20.         return False
    21.    
    22.     finally:
    23.         if cursor:
    24.             cursor.close()
    25.         if connection:
    26.             connection.close()
    复制代码
    2.2 存在的问题


    • 异常处理不够精细:仅打印错误信息并回滚,没有针对特定错误(如
      1. Duplicate entry
      复制代码
      )进行特殊处理。
    • 业务逻辑耦合度低:当数据重复时,可能需要执行额外操作(如更新记录状态),但原始代码没有提供这样的扩展点。

    3. 优化方案


    3.1 目标


    • 捕获特定异常:当错误信息包含
      1. Duplicate entry
      复制代码
      时,执行额外逻辑(如调用
      1. update_is_deal
      复制代码
      方法)。
    • 保持代码健壮性:确保事务回滚和资源释放不受影响。

    3.2 优化后的Python代码
    1. def insert_into_mysql(phone_numbers, prefix, province, city, url=None):
    2.     connection = None
    3.     cursor = None
    4.     try:
    5.         connection = get_db_connection()
    6.         if not connection:
    7.             print("数据库连接失败")
    8.             return False

    9.         cursor = connection.cursor()
    10.         data_to_insert = []
    11.         
    12.         for phone_number in phone_numbers:
    13.             if len(phone_number) == 11:
    14.                 suffix = phone_number[-4:]
    15.                 data_to_insert.append((prefix, suffix, phone_number, province, city))

    16.         if not data_to_insert:
    17.             print("警告: 没有有效的手机号可插入")
    18.             return False

    19.         cursor.executemany(INSERT_QUERY, data_to_insert)
    20.         connection.commit()
    21.         print(f"成功插入 {len(data_to_insert)} 条数据")
    22.         return True

    23.     except Exception as e:
    24.         print(f"插入数据失败: {e}")
    25.         if connection:
    26.             connection.rollback()
    27.         
    28.         # 检查是否是唯一键冲突
    29.         if "Duplicate entry" in str(e):
    30.             if url:  # 确保url有效
    31.                 update_is_deal(url, province, city)  # 执行额外逻辑
    32.         
    33.         return False
    34.    
    35.     finally:
    36.         if cursor:
    37.             cursor.close()
    38.         if connection:
    39.             connection.close()
    复制代码
    3.3 关键优化点


    • 精细化异常捕获:通过检查异常信息是否包含
      1. "Duplicate entry"
      复制代码
      ,判断是否为唯一键冲突。
    • 支持额外参数:新增
      1. url
      复制代码
      参数,确保
      1. update_is_deal
      复制代码
      方法可以正确执行。
    • 事务安全:即使执行额外逻辑,仍然保证事务回滚和资源释放。

    4. Java对比实现

    在Java中,MySQL的
    1. Duplicate entry
    复制代码
    错误通常对应
    1. SQLIntegrityConstraintViolationException
    复制代码
    ,我们可以采用类似的优化策略。

    4.1 Java版本优化代码
    1. import java.sql.*;
    2. import java.util.List;

    3. public class PhoneNumberDao {
    4.     private static final String INSERT_QUERY =
    5.         "INSERT INTO phone_numbers (prefix, suffix, phone_number, province, city) " +
    6.         "VALUES (?, ?, ?, ?, ?)";

    7.     public boolean insertIntoMysql(List<String> phoneNumbers, String prefix,
    8.                                   String province, String city, String url) {
    9.         Connection connection = null;
    10.         PreparedStatement statement = null;
    11.         
    12.         try {
    13.             connection = DatabaseUtil.getConnection(); // 获取数据库连接
    14.             connection.setAutoCommit(false); // 开启事务
    15.             
    16.             statement = connection.prepareStatement(INSERT_QUERY);
    17.             
    18.             for (String phoneNumber : phoneNumbers) {
    19.                 if (phoneNumber.length() == 11) {
    20.                     String suffix = phoneNumber.substring(7); // 后4位
    21.                     statement.setString(1, prefix);
    22.                     statement.setString(2, suffix);
    23.                     statement.setString(3, phoneNumber);
    24.                     statement.setString(4, province);
    25.                     statement.setString(5, city);
    26.                     statement.addBatch(); // 加入批处理
    27.                 }
    28.             }
    29.             
    30.             statement.executeBatch(); // 执行批处理
    31.             connection.commit(); // 提交事务
    32.             return true;
    33.             
    34.         } catch (SQLIntegrityConstraintViolationException e) {
    35.             // 捕获唯一键冲突异常
    36.             System.err.println("插入数据失败(唯一键冲突): " + e.getMessage());
    37.             if (connection != null) {
    38.                 try {
    39.                     connection.rollback(); // 回滚事务
    40.                 } catch (SQLException ex) {
    41.                     ex.printStackTrace();
    42.                 }
    43.             }
    44.             
    45.             if (url != null) {
    46.                 updateIsDeal(url, province, city); // 执行额外逻辑
    47.             }
    48.             return false;
    49.             
    50.         } catch (SQLException e) {
    51.             System.err.println("插入数据失败: " + e.getMessage());
    52.             if (connection != null) {
    53.                 try {
    54.                     connection.rollback();
    55.                 } catch (SQLException ex) {
    56.                     ex.printStackTrace();
    57.                 }
    58.             }
    59.             return false;
    60.             
    61.         } finally {
    62.             // 关闭资源
    63.             try {
    64.                 if (statement != null) statement.close();
    65.                 if (connection != null) connection.close();
    66.             } catch (SQLException e) {
    67.                 e.printStackTrace();
    68.             }
    69.         }
    70.     }

    71.     private void updateIsDeal(String url, String province, String city) {
    72.         // 实现更新逻辑
    73.         System.out.println("检测到重复数据,更新状态: " + url);
    74.     }
    75. }
    复制代码
    4.2 Java优化点


    • 精准捕获
      1. SQLIntegrityConstraintViolationException
      复制代码
      ,而不是笼统的
      1. SQLException
      复制代码

    • 批处理优化:使用
      1. addBatch()
      复制代码
      1. executeBatch()
      复制代码
      提高插入效率。
    • 事务管理:显式控制
      1. commit()
      复制代码
      1. rollback()
      复制代码
      ,确保数据一致性。

    5. 总结与最佳实践


    5.1 关键总结

    优化点Python 实现Java 实现异常捕获检查
    1. str(e)
    复制代码
    是否包含
    1. "Duplicate entry"
    复制代码
    捕获
    1. SQLIntegrityConstraintViolationException
    复制代码
    事务管理
    1. connection.rollback()
    复制代码
    1. connection.rollback()
    复制代码
    资源释放
    1. finally
    复制代码
    块关闭连接
    1. finally
    复制代码
    块关闭资源批处理优化
    1. cursor.executemany()
    复制代码
    1. addBatch()
    复制代码
    +
    1. executeBatch()
    复制代码

    5.2 最佳实践


    • 精细化异常处理:不要仅捕获
      1. Exception
      复制代码
      ,而应根据业务需求区分不同错误类型。
    • 事务安全:确保异常发生时能正确回滚,避免脏数据。
    • 资源释放:使用
      1. try-finally
      复制代码
      1. try-with-resources
      复制代码
      (Java)确保数据库连接关闭。
    • 日志记录:在异常处理时记录足够的信息,便于排查问题。

    6. 扩展思考


    • 是否应该先查询再插入?

      • 如果数据量较大,先查询再插入可能影响性能,直接捕获
        1. Duplicate entry
        复制代码
        更高效。

    • 如何优化
      1. update_is_deal
      复制代码
      逻辑?

      • 可以引入异步处理(如消息队列),避免影响主流程性能。

    • 是否可以用
      1. INSERT IGNORE
      复制代码
      1. ON DUPLICATE KEY UPDATE
      复制代码


      • 取决于业务需求,如果需要静默忽略重复数据,可以使用这些SQL语法。


    7. 结语

    通过本文的优化案例,我们学习了如何在Python和Java中精细化处理MySQL的
    1. Duplicate entry
    复制代码
    错误,并执行额外的业务逻辑。关键在于:

    • 精准捕获异常
    • 确保事务安全
    • 合理优化批处理
    到此这篇关于MySQL处理重复数据插入的处理方案的文章就介绍到这了,更多相关MySQL重复数据插入处理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    来源:https://www.jb51.net/database/339557p7k.htm
    免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

    最新评论

    QQ Archiver 手机版 小黑屋 福建二哥 ( 闽ICP备2022004717号|闽公网安备35052402000345号 )

    Powered by Discuz! X3.5 © 2001-2023

    快速回复 返回顶部 返回列表