首页 > 解决方案 > 如何频繁替换整个 SQL 表数据?

问题描述

我有一个运行 cron 的 Spring 应用程序。cron 每隔几分钟就会从外部 API 获取新数据。数据应该存储在数据库(MySQL)中,代替旧数据(旧数据应该被新数据覆盖)。数据需要被覆盖而不是更新。应用程序本身提供 REST API,因此客户端能够从数据库中获取数据。因此,不应该出现客户端因为有数据更新而看到数据库中的空数据或仅部分数据的情况。目前我已经尝试删除整个旧数据并插入新数据,但是有一个地方客户端只获取了一部分数据。我已经通过 Spring Data deleteAll 和 saveAll 方法进行了尝试。

@Override
@Transactional
public List<Country> overrideAll(@NonNull Iterable<Country> countries) {
    removeAllAndFlush();

    List<CountryEntity> countriesToCreate = stream(countries.spliterator(), false)
            .map(CountryEntity::from)
            .collect(toList());

    List<CountryEntity> createdCountries = repository.saveAll(countriesToCreate);

    return createdCountries.stream()
            .map(CountryEntity::toCountry)
            .collect(toList());
}

private void removeAllAndFlush() {
    repository.deleteAll();
    repository.flush();
}

我还考虑过有一个临时表来获取新数据,当数据完成时,只需用临时表替换主表。这是个好主意吗?还有其他想法吗?

标签: javamysqlsqlspring

解决方案


这是个好主意。您可以通过在另一个表上工作直到它准备好,然后通过重命名快速切换表来最大限度地减少停机时间。这也将提高用户的感知性能,因为不需要像使用 UPDATE/DELETE 时那样锁定记录。

在 MySQL 中,如果表上没有触发器,则可以使用 RENAME TABLE。它允许一次重命名多个表并且它以原子方式工作(即事务 - 如果发生任何错误,则不会进行任何更改)。您可以使用以下示例

RENAME TABLE countries TO countries_old, countries_new TO countries;
DROP TABLE countries_old; 

请参阅此处了解更多详情

https://dev.mysql.com/doc/refman/5.7/en/rename-table.html


推荐阅读