【问题标题】:Spring JDBC Template batchUpdate to update thousands of records in a tbaleSpring JDBC Template批量更新更新表中的数千条记录
【发布时间】:2017-12-09 19:31:06
【问题描述】:

我有一个更新查询,我试图通过 spring jdbc 模板的 batchUpdate 方法执行。此更新查询可能会匹配 EVENT_DYNAMIC_ATTRIBUTE 表中需要更新的 1000 行。除了超时之外,更新表中的数千行是否会导致生产数据库中的任何问题?比如,它会导致数据库崩溃还是会降低整个数据库引擎的其他连接性能……等等?

有没有更好的方法来实现这一点,而不是在 Spring JDBC 模板或 JPA 中触发单个更新查询?我对 jdbc 模板有以下设置。

this.jdbc = new JdbcTemplate(ds);
jdbc.setFetchSize(1000);
jdbc.setQueryTimeout(0); // zero means there is no limit

更新查询:

UPDATE EVENT_DYNAMIC_ATTRIBUTE eda
   SET eda.ATTRIBUTE_VALUE = 'claim',
       eda.LAST_UPDATED_DATE = SYSDATE,
       eda.LAST_UPDATED_BY = 'superUsers'
 WHERE     eda.DYNAMIC_ATTRIBUTE_NAME_ID = 4002
       AND eda.EVENT_ID IN
              (WITH category_data
                       AS (    SELECT c.CATEGORY_ID
                                 FROM CATEGORY c
                           START WITH CATEGORY_ID = 495984
                           CONNECT BY PARENT_ID = PRIOR CATEGORY_ID)
               SELECT event_id
                 FROM event e
                WHERE EXISTS
                         (SELECT 't'
                            FROM category_data cd
                           WHERE cd.CATEGORY_ID = e.PRIMARY_CATEGORY_ID))

【问题讨论】:

    标签: java oracle sql-update spring-jdbc batch-updates


    【解决方案1】:

    如果是一次性的,我通常会先选择需要更新的记录并放入临时表或 csv 中,并确保将这些记录的主键保存在表中或.csv。然后我从临时表或csv中批量读取记录,并使用主键在表中进行更新。这样表不会长时间锁定,您可以在需要更新的批处理中添加固定的记录集,并且使用主键完成更新,因此速度非常快。如果任何更新失败,那么您可以通过在日志文件或错误表中注销失败记录的主键来了解哪些记录失败。我已经多次使用这种方法来更新 PROD 数据库中的数百万条记录,因为它是一种非常安全的方法。

    【讨论】:

    • 不,这不是一次性的,我们计划在 JMX 控制台中通过 MBean 将其作为可用功能提供,超级用户偶尔会执行此活动,需要在 PROD 中完成而不会导致任何原始表中的问题或延迟,并且更新跨越多个表
    • 但是您上面的更新查询发生在一个表中。即使您想偶尔执行此操作,也应该应用相同的概念,首先从受影响的表中检索数据,因为检索通常不会对表进行锁定。检索数据后,使用其主键更新受影响的表。
    • 我只提供了上面的一个示例查询,我有一堆这样的查询并作为 batchUpdate 的一部分发送,不允许在 PROD 中创建临时表。在这个 batchUpdate 期间我也有一些事务超时问题,因为这些更新查询中的每一个都可能更新 100 条记录中的 100 条记录
    • 是的,更新会导致事务超时,并且不需要额外的 PROD 临时表,而是可以将获取的记录保存在内存中。这里的要点是,首先选择不应该锁定表上的任何记录,然后将这些获取的记录保留在内存中,然后使用主键分批 1000 运行更新查询。此外,如果您的选择查询超时,那么您需要通过修改查询或在表中添加索引来提高查询性能。
    • 我几乎遵循这种方法,但每次获取 10,000 条记录并通过将所有累积更新查询发送到数据库来调用 batchUpdate(这意味着要更新 100、000 条记录,我构建了 10 个更新查询和发送到数据库),整个批处理正在获取事务超时(意外错误:org.springframework.transaction.TransactionTimedOutException:事务超时:截止日期是),有没有办法在调用JdbTemplate的batchUpdate之前设置自定义事务超时?跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多