设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间01 现在时间01 缓存数据 轻轻的闭上眼睛,慢慢的酝酿心情,将白天所有烦恼不快撒向天空,随着流星的坠落一起沉淀,愿今夜有个好梦,晚安!

轻轻的闭上眼睛,慢慢的酝酿心情,将白天所有烦恼不快撒向天空,随着流星的坠落一起沉淀,愿今夜有个好梦,晚安!

查看: 580|回复: 0

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

[复制链接]

  离线 

TA的专栏

  • 打卡等级:即来则安
  • 打卡总天数:25
  • 打卡月天数:0
  • 打卡总奖励:288
  • 最近打卡:2025-03-18 10:18:58
等级头衔

等級:晓枫资讯-上等兵

在线时间
0 小时

积分成就
威望
0
贡献
308
主题
270
精华
0
金钱
1177
积分
628
注册时间
2023-2-11
最后登录
2025-5-31

发表于 2025-5-26 22:37:58 | 显示全部楼层 |阅读模式
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重复数据插入处理内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

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