【问题标题】:How do I create indexes concurrently with flyway in postgres?如何在 postgres 中与 flyway 同时创建索引?
【发布时间】:2021-08-31 17:28:44
【问题描述】:

Postgres 允许在不使用 CONCURRENTLY 选项锁定表的情况下创建索引。事务中不允许使用此选项,因此当将其添加到 flyway 迁移脚本时,flyway 会失败:

错误:由 org.postgresql.util.PSQLException 引起:错误:CREATE INDEX CONCURRENTLY 不能在事务块内运行

ActiveRecord 支持disable_ddl_transaction! 来解决这种情况。 flyway 是否支持某种方式在事务之外运行这样的脚本?

【问题讨论】:

    标签: postgresql flyway


    【解决方案1】:

    这是在 Flyway 4.1 中实现的,请参阅票证 851Non-Transactional PostgreSQL Support in Flyway(链接已损坏)。

    此功能通过检测应在没有事务的情况下执行语句来工作。据我所知,目前只支持 PostgreSQL。

    第一个障碍是检测何时需要在外部运行迁移 的一笔交易。两条前进的道路是显而易见的。第一条路径,[..], 是创建文件名注释。第二条路径是添加一个 Flyway 的语句解析器检测非事务性命令和 以适当的隔离级别运行它们。尽管有额外的工作 就他们而言,Boxfuse 团队坚定不移地 遵循第二条路径。它提供了更好的用户体验 Flyway 的长期用户。

    默认情况下,以这种方式执行的迁移应该只包含需要在没有事务的情况下执行的语句。默认情况下不允许将其与事务语句混合使用,需要通过属性启用。

    创建迁移不得混合事务性与 非事务性语句创建了可能引入的限制 未来用户看不到的问题。万一这个未知 需要通常在一个内部运行的 DDL 的情况 交易需要处理,一个属性叫做 flyway.allowMixedMigrations 被添加到配置中。默认情况下它是假的。我强烈建议永远不要打开它。

    非事务性处理的语句由PostgreSQLParser中的代码确定:

    @Override
    protected Boolean detectCanExecuteInTransaction(String simplifiedStatement, List<Token> keywords) {
        if (CREATE_DATABASE_TABLESPACE_SUBSCRIPTION_REGEX.matcher(simplifiedStatement).matches()
                || ALTER_SYSTEM_REGEX.matcher(simplifiedStatement).matches()
                || CREATE_INDEX_CONCURRENTLY_REGEX.matcher(simplifiedStatement).matches()
                || REINDEX_REGEX.matcher(simplifiedStatement).matches()
                || VACUUM_REGEX.matcher(simplifiedStatement).matches()
                || DISCARD_ALL_REGEX.matcher(simplifiedStatement).matches()) {
            return false;
        }
    
        boolean isDBVerUnder12 = true;
        try {
            isDBVerUnder12 = !parsingContext.getDatabase().getVersion().isAtLeast("12");
        } catch (Exception e) {
            LOG.debug("Unable to determine database version: " + e.getMessage());
        }
        
        if (isDBVerUnder12 && ALTER_TYPE_ADD_VALUE_REGEX.matcher(simplifiedStatement).matches()) {
            return false;
        }
    
        return null;
    }
    

    【讨论】:

    • @ZhongxiaZhou 我更新了 Flyway 代码(和代码)中类的链接,但是第二个链接根本不存在,我找不到新的位置,也没有在 archive.org 中。当我引用其中的部分内容时,我已将链接保留在原处。
    【解决方案2】:

    目前还没有。当前所有迁移都在一个事务中运行。随时在问题跟踪器中提交增强请求。

    【讨论】:

    • 2015 - 仍然无法同时运行 create index 和 flyway ;-)
    • 更正:似乎缺少一个示例,功能已经实现:github.com/flyway/flyway/issues/1072
    • 好像有人为 Java API 构建了这个功能可以通过 flyway 的命令行版本完成吗?
    【解决方案3】:

    根据这篇文章:

    Flyway migration hangs for postgres CREATE INDEX CONCURRENTLY

    您可以将 NT 作为前缀添加到您的迁移中

    V201609121806__create_index_for_table.sql

    变成

    NTV201609121806__create_index_for_table.sql

    【讨论】:

    • 这实际上是行不通的。请参阅 Axel Fontaine 的回答。自定义解析器 PR 从未合并,我不确定如何实际解决此问题。
    猜你喜欢
    • 2021-09-05
    • 1970-01-01
    • 2017-08-24
    • 1970-01-01
    • 1970-01-01
    • 2013-07-22
    • 1970-01-01
    • 2018-06-25
    • 1970-01-01
    相关资源
    最近更新 更多