代码之家  ›  专栏  ›  技术社区  ›  Subhajit

我们可以创建数据库并在新数据库上使用flyway执行迁移吗?[副本]

  •  0
  • Subhajit  · 技术社区  · 1 年前

    问题: 是否可以在迁移脚本中创建一个新的数据库,然后连接到它?怎么用?

    我的场景: 我试图在我的Java项目中使用flyway(使用Jersey2.4+tomcat 7+PostgreSQL 9.3.1+EclipseLink的RESTful应用程序)来管理使用git的不同开发人员之间的更改。我编写了init脚本并运行了它:

    PGPASSWORD='123456' psql -U postgres -f migration/V1__initDB.sql
    

    而且效果很好。问题是我不能用我的脚本创建新的数据库。当我在脚本中包含以下行时:

    CREATE DATABASE my_database OWNER postgres ENCODING 'UTF8';
    

    我得到这个错误:

    org.postgresql.util.PSQLException: ERROR: CREATE DATABASE cannot run inside a transaction block
        at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2157)
        at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1886)
        at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
        at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:555)
        at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:403)
        at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:395)
        at com.googlecode.flyway.core.dbsupport.JdbcTemplate.executeStatement(JdbcTemplate.java:230)
        at com.googlecode.flyway.core.dbsupport.SqlScript.execute(SqlScript.java:89)
        at com.googlecode.flyway.core.resolver.sql.SqlMigrationExecutor.execute(SqlMigrationExecutor.java:72)
        at com.googlecode.flyway.core.command.DbMigrate$2.doInTransaction(DbMigrate.java:252)
        at com.googlecode.flyway.core.command.DbMigrate$2.doInTransaction(DbMigrate.java:250)
        at com.googlecode.flyway.core.util.jdbc.TransactionTemplate.execute(TransactionTemplate.java:56)
        at com.googlecode.flyway.core.command.DbMigrate.applyMigration(DbMigrate.java:250)
        at com.googlecode.flyway.core.command.DbMigrate.access$700(DbMigrate.java:47)
        at com.googlecode.flyway.core.command.DbMigrate$1.doInTransaction(DbMigrate.java:189)
        at com.googlecode.flyway.core.command.DbMigrate$1.doInTransaction(DbMigrate.java:138)
        at com.googlecode.flyway.core.util.jdbc.TransactionTemplate.execute(TransactionTemplate.java:56)
        at com.googlecode.flyway.core.command.DbMigrate.migrate(DbMigrate.java:137)
        at com.googlecode.flyway.core.Flyway$1.execute(Flyway.java:872)
        at com.googlecode.flyway.core.Flyway$1.execute(Flyway.java:819)
        at com.googlecode.flyway.core.Flyway.execute(Flyway.java:1200)
        at com.googlecode.flyway.core.Flyway.migrate(Flyway.java:819)
        at ir.chom.MyApp.<init>(MyApp.java:28)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
        at org.glassfish.hk2.utilities.reflection.ReflectionHelper.makeMe(ReflectionHelper.java:1117)
        at org.jvnet.hk2.internal.Utilities.justCreate(Utilities.java:867)
        at org.jvnet.hk2.internal.ServiceLocatorImpl.create(ServiceLocatorImpl.java:814)
        at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:906)
        at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:898)
        at org.glassfish.jersey.server.ApplicationHandler.createApplication(ApplicationHandler.java:300)
        at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:279)
        at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:302)
        at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:167)
        at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:349)
        at javax.servlet.GenericServlet.init(GenericServlet.java:160)
        at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1280)
        at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1091)
        at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5176)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5460)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        at org.apache.catalina.core.StandardContext.reload(StandardContext.java:3954)
        at org.apache.catalina.loader.WebappLoader.backgroundProcess(WebappLoader.java:426)
        at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1345)
        at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1530)
        at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1540)
        at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1540)
        at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1519)
        at java.lang.Thread.run(Thread.java:724)
    

    这似乎是使用JDBC的问题 autocommit 选项。此选项可以通过以下方式禁用:

    Connection connection = dataSource.getConnection();
    Connection.setAutoCommit(false);        // Disables auto-commit.
    

    但我不知道如何将此选项传递给flyway连接。此外,如果我解决了这个问题,我想我将无法将密码传递给 \c 命令。

    0 回复  |  直到 9 年前
        1
  •  54
  •   Axel Fontaine    11 年前

    Flyway始终在jdbc连接字符串中使用的数据库内运行。

    连接后,所有脚本都在事务中运行。由于事务中不支持CREATE DATABASE,您将无法完成所需的任务。

    但是,您可以做的是创建一个模式。如果你把它指向一个不存在的地方,Flyway甚至会为你做这件事。

        2
  •  12
  •   stikku    11 年前

    我不知道这在飞行途中是否可行。

    Flyway旨在连接到已经存在的数据库(无论它是否为空)。将数据库创建与数据库迁移分开也是一种很好的做法。

        3
  •  8
  •   Gili    6 年前

    以下是一个对我有效的解决方法(假设使用Maven插件):

    通过两次执行配置插件。第一次执行创建数据库。第二次执行将迁移现有数据库。

        <plugin>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-maven-plugin</artifactId>
            <version>${flyway.version}</version>
            <executions>
                <execution>
                    <id>create-db</id>
                    <goals>
                        <goal>migrate</goal>
                    </goals>
                    <configuration>
                        <driver>org.postgresql.Driver</driver>
                        <url>jdbc:postgresql://database-server/</url>
                        <user>postgres</user>
                        <password>password</password>
                        <placeholders>
                            <DATABASE.NAME>MyDatabase</DATABASE.NAME>
                        </placeholders>
                        <locations>
                            <location>com/foo/bar/database/create</location>
                        </locations>
                    </configuration>
                </execution>
                <execution>
                    <id>migrate-db</id>
                    <goals>
                        <goal>migrate</goal>
                    </goals>
                    <configuration>
                        <driver>org.postgresql.Driver</driver>
                        <url>jdbc:postgresql://database-server/MyDatabase</url>
                        <user>postgres</user>
                        <password>password</password>
                        <locations>
                            <location>com/foo/bar/database/migrate</location>
                        </locations>
                    </configuration>
                </execution>
            </executions>
            <dependencies>
                <dependency>
                    <groupId>org.postgresql</groupId>
                    <artifactId>postgresql</artifactId>
                    <version>${postgresql.version}</version>
                </dependency>
            </dependencies>
        </plugin>
    

    然后添加 V1__Created_database.sql com/foo/bar/database/create 目录。此文件包含:

    CREATE DATABASE ${DATABASE.NAME}

        4
  •  1
  •   Omar Ghazi    4 年前

    Flyway无法为您创建数据库。 如果您没有通过以下方式创建模式,它可以创建模式

    flyway.schemas: schema1,schema2
    
        5
  •  1
  •   devil0150 lialzm    4 年前

    您可以尝试本期中的建议: https://github.com/flyway/flyway/issues/2556 ,使用 createDatabaseIfNotExist 在flyway中配置mysqlurl中的参数,如下所示:

      <groupId>org.flywaydb</groupId>
        <artifactId>flyway-maven-plugin</artifactId>
        <version>6.4.1</version>
        <configuration>
            <url>jdbc:mysql://localhost:3306/<databaseName>?createDatabaseIfNotExist=true</url>
            <user>root</user>
            <password>root</password>
        </configuration>
    
        6
  •  0
  •   Subhajit    1 年前

    我为这种情况创建了一个解决方法。我有一个用例,可以在多租户应用程序设置中为每个租户创建数据库。

    添加了create db脚本作为 "Repeatable Migrations" .

    我进行了两次飞行路线迁移,以实现:

    1. 弗斯特 flyway.migrate() 从默认/主数据库创建数据库:添加一个sql文件 R__create_db.sql 其内容如下:

    创建数据库“${db_name}”;

    1. 第二 flyway.migrate() 使用上述新数据库的数据源创建表和其他操作。
        7
  •  -2
  •   Kiarash Zamanifar    8 年前

    如果你有模式 数据库 在脚本的V1中创建命令,flyway可以生成它,但不能生成数据库:

    flyway -baselineOnMigrate=true -url=jdbc:mysql://localhost/ -schemas=test_db -user=root -password=root_pass -locations=filesystem:/path/to/scrips/ migrate
    

    与脚本文件中的类似:

    DROP SCHEMA IF EXISTS `test_db` ;
    CREATE SCHEMA `test_db` COLLATE utf8_general_ci ;