如何创建具有快照隔离级别的 Flyway 模式历史记录?
How to create Flyway schema history with snapshot isolation level?
我正在研究是否可以在我一直从事的项目中使用 Flyway 进行数据库架构迁移...数据库迁移是手动完成的,我真的很想开始使用 Flyway。
这是一个 Spring 引导 (v2.2.0) 应用程序,我正在尝试使用 Flyway 版本 v.7.1.1 配置迁移。
我已从数据库生成现有架构并将其设置为 V1 基础版本。但是,当尝试 运行 应用程序时(使用 baseline-on-migrate: true),迁移因异常而失败:
Caused by: org.flywaydb.core.internal.sqlscript.FlywaySqlScriptException:
Migration failed
-----------------
SQL State : S0001
Error Code : 3964
Message : Transaction failed because this DDL statement is not allowed inside a snapshot isolation transaction. Since metadata is not versioned, a metadata change can lead to inconsistency if mixed within snapshot isolation.
Location : ()
Line : 1
Statement : CREATE TABLE [TestDB].[dbo].[flyway_schema_history] (
[installed_rank] INT NOT NULL,
[version] NVARCHAR(50),
[description] NVARCHAR(200),
[type] NVARCHAR(20) NOT NULL,
[script] NVARCHAR(1000) NOT NULL,
[checksum] INT,
[installed_by] NVARCHAR(100) NOT NULL,
[installed_on] DATETIME NOT NULL DEFAULT GETDATE(),
[execution_time] INT NOT NULL,
[success] BIT NOT NULL
);
在应用程序配置中,HikariCP 数据源配置设置为使用:
transaction-isolation: TRANSACTION_SQL_SERVER_SNAPSHOT_ISOLATION_LEVEL
如果事务隔离更改为例如TRANSACTION_READ_COMMITTED迁移成功。我可以按预期执行所有其他迁移。
软件架构师告诉我快照隔离级别背后的原因是因为应用程序用于生成大量报告,这可能需要几个小时,而快照隔离级别“保护我们免受应用程序冻结和锁定”。
我尝试通过创建回调来解决这个问题,我可以在 运行 时间、beforeMigrate 和 afterMigrate Java 回调中更改事务隔离,但是 HikariDataSource 配置不能在 运行 时间内更改。
有人可以提供一些建议吗,迁移(和创建基线模式)是否可以通过快照隔离实现?
我是 SQL Server 中快照隔离的超级粉丝,但它并不适合作为所有部署的隔离级别。
以下是需要考虑的三个主要事项:
1。关于 DDL 和显式多语句事务的快照隔离限制
快照隔离非常有用,但是 SQL 服务器确实限制了它的用途,如错误消息所示:
Transaction failed because this DDL statement is not allowed inside a
snapshot isolation transaction. Since metadata is not versioned, a
metadata change can lead to inconsistency if mixed within snapshot
isolation.
这不仅适用于创建 flyway_schema_history table,SQL 服务器还会将此规则应用于您在迁移脚本中进行的其他 DDL 更改。
更多信息在 documentation here:
SQL Server does not support versioning of metadata. For this reason,
there are restrictions on what DDL operations can be performed in an
explicit transaction that is running under snapshot isolation. The
following DDL statements are not permitted under snapshot isolation
after a BEGIN TRANSACTION statement: ALTER TABLE, CREATE INDEX, CREATE
XML INDEX, ALTER INDEX, DROP INDEX, DBCC REINDEX, ALTER PARTITION
FUNCTION, ALTER PARTITION SCHEME, or any common language runtime (CLR)
DDL statement.
2。 DDL操作无论如何都需要Schema Modification锁
此外,即使在快照隔离下,DDL 更改也需要高级模式修改锁 (SCH-M),这需要对 table 进行独占访问。关于这个 in that same paper:
The SQL Server Database Engine uses schema modification (Sch-M) locks
during a table data definition language (DDL) operation, such as
adding a column or dropping a table. During the time that it is held,
the Sch-M lock prevents concurrent access to the table. This means the
Sch-M lock blocks all outside operations until the lock is released.
Some data manipulation language (DML) operations, such as table
truncation, use Sch-M locks to prevent access to affected tables by
concurrent operations.
换句话说,当涉及到迁移脚本中可能有的任何 DDL 操作时,快照隔离不能't/won提供更少的阻塞和应用程序冻结。
3。如果在数据修改上使用 Snapshot Iso,则需要准备好处理 Update Conflicts
快照可用于更新 DML 语句中的数据,但它确实增加了复杂性,您需要为其添加错误处理。可能会发生更新冲突if data in a table may be modified by two processes at the same time:
If the data row has been modified outside of the snapshot transaction,
an update conflict occurs and the snapshot transaction is terminated.
The update conflict is handled by the SQL Server Database Engine and
there is no way to disable the update conflict detection.
快照隔离可以提供帮助的地方
根据您所说的,我认为应用程序/报告继续使用快照隔离是有意义的,但是您 运行 您的 部署 默认读取提交隔离级别的 Flyway。
只要 app/Reports 使用快照隔离,这意味着它们不会被任何 inserts/updates/deletes 您在飞路部署中所做的阻止。
您所做的任何更改架构的 DDL 都可能会阻止报告。但是,在部署中使用快照隔离不会为您改变这一点——无论哪种方式,您都需要 SCH-M 锁。
肯德拉
我通过为 Flyway 迁移创建单独的数据源,设法绕过应用程序的 Hikari 数据源隔离级别,其中事务隔离设置为 READ_COMMITED。
Flyway 迁移 运行 成功,主数据源配置未受影响(使用 SNAPSHOT 隔离)。
@Bean
@FlywayDataSource
public DataSource flywayDataSource(@Autowired @Qualifier(value = "primaryDataSource") DataSource primaryDataSource) {
HikariDataSource hds = (HikariDataSource) primaryDataSource;
HikariConfig flywayHikariConfig = new HikariConfig();
hds.copyStateTo(flywayHikariConfig);
flywayHikariConfig.setTransactionIsolation(IsolationLevel.TRANSACTION_READ_COMMITTED.toString());
return new HikariDataSource(flywayHikariConfig);
}
我无法将类似的逻辑应用于 Flyway 回调,Java 或 SQL,其中 ISO 级别已更改。
但是,我认为这可以通过在 some Flyway 配置 bean 上设置 @Transactional(isolation=Isolation.READ_COMMITTED) 来完成,但我无法使其工作(例如尝试 FlywayMigrationStrategy).
我正在研究是否可以在我一直从事的项目中使用 Flyway 进行数据库架构迁移...数据库迁移是手动完成的,我真的很想开始使用 Flyway。
这是一个 Spring 引导 (v2.2.0) 应用程序,我正在尝试使用 Flyway 版本 v.7.1.1 配置迁移。
我已从数据库生成现有架构并将其设置为 V1 基础版本。但是,当尝试 运行 应用程序时(使用 baseline-on-migrate: true),迁移因异常而失败:
Caused by: org.flywaydb.core.internal.sqlscript.FlywaySqlScriptException:
Migration failed
-----------------
SQL State : S0001
Error Code : 3964
Message : Transaction failed because this DDL statement is not allowed inside a snapshot isolation transaction. Since metadata is not versioned, a metadata change can lead to inconsistency if mixed within snapshot isolation.
Location : ()
Line : 1
Statement : CREATE TABLE [TestDB].[dbo].[flyway_schema_history] (
[installed_rank] INT NOT NULL,
[version] NVARCHAR(50),
[description] NVARCHAR(200),
[type] NVARCHAR(20) NOT NULL,
[script] NVARCHAR(1000) NOT NULL,
[checksum] INT,
[installed_by] NVARCHAR(100) NOT NULL,
[installed_on] DATETIME NOT NULL DEFAULT GETDATE(),
[execution_time] INT NOT NULL,
[success] BIT NOT NULL
);
在应用程序配置中,HikariCP 数据源配置设置为使用:
transaction-isolation: TRANSACTION_SQL_SERVER_SNAPSHOT_ISOLATION_LEVEL
如果事务隔离更改为例如TRANSACTION_READ_COMMITTED迁移成功。我可以按预期执行所有其他迁移。 软件架构师告诉我快照隔离级别背后的原因是因为应用程序用于生成大量报告,这可能需要几个小时,而快照隔离级别“保护我们免受应用程序冻结和锁定”。
我尝试通过创建回调来解决这个问题,我可以在 运行 时间、beforeMigrate 和 afterMigrate Java 回调中更改事务隔离,但是 HikariDataSource 配置不能在 运行 时间内更改。
有人可以提供一些建议吗,迁移(和创建基线模式)是否可以通过快照隔离实现?
我是 SQL Server 中快照隔离的超级粉丝,但它并不适合作为所有部署的隔离级别。
以下是需要考虑的三个主要事项:
1。关于 DDL 和显式多语句事务的快照隔离限制
快照隔离非常有用,但是 SQL 服务器确实限制了它的用途,如错误消息所示:
Transaction failed because this DDL statement is not allowed inside a snapshot isolation transaction. Since metadata is not versioned, a metadata change can lead to inconsistency if mixed within snapshot isolation.
这不仅适用于创建 flyway_schema_history table,SQL 服务器还会将此规则应用于您在迁移脚本中进行的其他 DDL 更改。
更多信息在 documentation here:
SQL Server does not support versioning of metadata. For this reason, there are restrictions on what DDL operations can be performed in an explicit transaction that is running under snapshot isolation. The following DDL statements are not permitted under snapshot isolation after a BEGIN TRANSACTION statement: ALTER TABLE, CREATE INDEX, CREATE XML INDEX, ALTER INDEX, DROP INDEX, DBCC REINDEX, ALTER PARTITION FUNCTION, ALTER PARTITION SCHEME, or any common language runtime (CLR) DDL statement.
2。 DDL操作无论如何都需要Schema Modification锁
此外,即使在快照隔离下,DDL 更改也需要高级模式修改锁 (SCH-M),这需要对 table 进行独占访问。关于这个 in that same paper:
The SQL Server Database Engine uses schema modification (Sch-M) locks during a table data definition language (DDL) operation, such as adding a column or dropping a table. During the time that it is held, the Sch-M lock prevents concurrent access to the table. This means the Sch-M lock blocks all outside operations until the lock is released.
Some data manipulation language (DML) operations, such as table truncation, use Sch-M locks to prevent access to affected tables by concurrent operations.
换句话说,当涉及到迁移脚本中可能有的任何 DDL 操作时,快照隔离不能't/won提供更少的阻塞和应用程序冻结。
3。如果在数据修改上使用 Snapshot Iso,则需要准备好处理 Update Conflicts
快照可用于更新 DML 语句中的数据,但它确实增加了复杂性,您需要为其添加错误处理。可能会发生更新冲突if data in a table may be modified by two processes at the same time:
If the data row has been modified outside of the snapshot transaction, an update conflict occurs and the snapshot transaction is terminated. The update conflict is handled by the SQL Server Database Engine and there is no way to disable the update conflict detection.
快照隔离可以提供帮助的地方
根据您所说的,我认为应用程序/报告继续使用快照隔离是有意义的,但是您 运行 您的 部署 默认读取提交隔离级别的 Flyway。
只要 app/Reports 使用快照隔离,这意味着它们不会被任何 inserts/updates/deletes 您在飞路部署中所做的阻止。
您所做的任何更改架构的 DDL 都可能会阻止报告。但是,在部署中使用快照隔离不会为您改变这一点——无论哪种方式,您都需要 SCH-M 锁。
肯德拉
我通过为 Flyway 迁移创建单独的数据源,设法绕过应用程序的 Hikari 数据源隔离级别,其中事务隔离设置为 READ_COMMITED。 Flyway 迁移 运行 成功,主数据源配置未受影响(使用 SNAPSHOT 隔离)。
@Bean
@FlywayDataSource
public DataSource flywayDataSource(@Autowired @Qualifier(value = "primaryDataSource") DataSource primaryDataSource) {
HikariDataSource hds = (HikariDataSource) primaryDataSource;
HikariConfig flywayHikariConfig = new HikariConfig();
hds.copyStateTo(flywayHikariConfig);
flywayHikariConfig.setTransactionIsolation(IsolationLevel.TRANSACTION_READ_COMMITTED.toString());
return new HikariDataSource(flywayHikariConfig);
}
我无法将类似的逻辑应用于 Flyway 回调,Java 或 SQL,其中 ISO 级别已更改。 但是,我认为这可以通过在 some Flyway 配置 bean 上设置 @Transactional(isolation=Isolation.READ_COMMITTED) 来完成,但我无法使其工作(例如尝试 FlywayMigrationStrategy).