微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何创建具有快照隔离级别的Flyway模式历史记录?

如何解决如何创建具有快照隔离级别的Flyway模式历史记录?

我正在研究我正在进行的项目上是否可以使用Flyway进行数据库模式迁移...数据库迁移是手动完成的,我真的很想开始使用Flyway。

这是一个Spring Boot(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_sql_SERVER_SNAPSHOT_ISOLATION_LEVEL

如果事务隔离更改为例如 TRANSACTION_READ_COMMITTED 迁移成功。我可以按预期执行所有其他迁移。 软件架构师告诉我快照隔离级别背后的原因是因为应用程序用于生成大量报告,这可能需要几个小时,而快照隔离级别“可以保护我们免受应用程序冻结和锁定”。

我试图通过创建回调来解决此问题,在该回调中我可以在运行时,beforeMigrate和afterMigrate Java回调中更改事务隔离,但是无法在运行时更改HikariDataSource配置。

有人可以提供一些建议吗,是否可以通过快照隔离进行迁移(和创建基线架构)?

解决方法

我是SQL Server中快照隔离的忠实拥护者,但它不适合作为所有部署的隔离级别。

这是要考虑的三件事:

1。有关DDL和显式多语句事务的快照隔离的限制

快照隔离非常有用,但是SQL Server确实限制了它的用途,因为错误消息表明:

交易失败,因为在内部不允许该DDL语句 快照隔离事务。由于未对元数据进行版本控制,因此 如果将元数据更改混入快照中,则可能导致不一致 隔离。

这不适用于创建flyway_schema_history表,SQL Server还将将此规则应用于迁移脚本中的其他DDL更改。

更多信息在documentation here中:

SQL Server不支持元数据的版本控制。为此原因, 在可以执行的DDL操作上有限制 在快照隔离下运行的显式事务。的 快照隔离下不允许以下DDL语句 在BEGIN TRANSACTION语句之后:ALTER TABLE,CREATE INDEX,CREATE XML索引,ALTER索引,DROP索引,DBCC REINDEX,ALTER分区 功能,更改分区方案或任何公共语言运行库(CLR) DDL语句。

2。无论什么,DDL操作都需要模式修改锁

此外,即使在快照隔离下,DDL更改也将需要高级模式修改锁(SCH-M),这需要对表进行独占访问。关于in that same paper的更多信息:

SQL Server数据库引擎使用架构修改(Sch-M)锁 在表数据定义语言(DDL)操作期间,例如 添加列或删除表。在举行期间, Sch-M锁阻止并发访问表。这意味着 Sch-M锁会阻止所有外部操作,直到释放锁为止。

某些数据操作语言(DML)操作,例如表 截断,使用Sch-M锁来防止通过以下方式访问受影响的表 并发操作。

换句话说,当涉及到迁移脚本中可能具有的任何DDL操作时,快照隔离不能/不会提供更少的阻止和应用程序冻结。

3。如果对数据修改使用Snapshot Iso,则需要做好处理更新冲突的准备

快照可用于更新DML语句中的数据,但是它确实增加了复杂性,您将需要为其添加错误处理。更新冲突可能会发生if data in a table may be modified by two processes at the same time

如果数据行在快照事务之外被修改, 发生更新冲突,快照事务终止。 更新冲突由SQL Server数据库引擎处理,并且 无法禁用更新冲突检测。

快照隔离可以提供帮助的地方

从您所说的来看,我认为应用程序/报告继续使用快照隔离是有意义的,但是对于您来说,您可以在Flyway中以默认的“读取已提交隔离”级别运行部署

只要应用程序/报表正在使用快照隔离,这意味着它们不会被您在flyway部署中执行的任何插入/更新/删除操作所阻止。

您更改架构的任何DDL都可能会阻止报告。但是,在部署中使用快照隔离不会改变您的情况,您需要使用SCH-M锁。

肯德拉

,

通过为Flyway迁移创建单独的数据源(事务隔离设置为READ_COMMITED),我设法绕过了应用程序的Hikari数据源隔离级别。 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);
}

我无法在更改ISO级别的Flyway回调,Java或SQL中应用类似的逻辑。 但是,我认为可以通过在 some Flyway配置bean上设置@Transactional(isolation = Isolation.READ_COMMITTED)来实现此目的,但是我无法使其正常工作(例如,尝试使用 FlywayMigrationStrategy )。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?