@@ -172,7 +172,7 @@ func (p *Provider) runIndividually(
172172 if err != nil {
173173 return err
174174 }
175- if useTx {
175+ if useTx && ! p . cfg . isolateDDL {
176176 return beginTx (ctx , conn , func (tx * sql.Tx ) error {
177177 if err := p .runMigration (ctx , tx , m , direction ); err != nil {
178178 return err
@@ -316,20 +316,34 @@ func (p *Provider) tryEnsureVersionTable(ctx context.Context, conn *sql.Conn) er
316316 }
317317 // Fallthrough to create the table.
318318 } else if err != nil {
319- return fmt .Errorf ("failed to check if version table exists: %w" , err )
319+ return fmt .Errorf ("check if version table exists: %w" , err )
320320 }
321321
322- if err := beginTx (ctx , conn , func (tx * sql.Tx ) error {
323- if err := p .store .CreateVersionTable (ctx , tx ); err != nil {
324- return err
322+ if p .cfg .isolateDDL {
323+ // If isolation is enabled, we create the version table separately to ensure subsequent
324+ // DML operations are not mixed with DDL.
325+ if err := p .store .CreateVersionTable (ctx , conn ); err != nil {
326+ return retry .RetryableError (fmt .Errorf ("create version table: %w" , err ))
327+ }
328+ if err := p .store .Insert (ctx , conn , database.InsertRequest {Version : 0 }); err != nil {
329+ return retry .RetryableError (fmt .Errorf ("insert zero version: %w" , err ))
330+ }
331+ } else {
332+ // If DDL isolation is not enabled, we can create the version table and insert the zero
333+ // version in a single transaction.
334+ if err := beginTx (ctx , conn , func (tx * sql.Tx ) error {
335+ if err := p .store .CreateVersionTable (ctx , tx ); err != nil {
336+ return err
337+ }
338+ return p .store .Insert (ctx , tx , database.InsertRequest {Version : 0 })
339+ }); err != nil {
340+ // Mark the error as retryable so we can try again. It's possible that another instance
341+ // is creating the table at the same time and the checks above will succeed on the next
342+ // iteration.
343+ return retry .RetryableError (fmt .Errorf ("create version table: %w" , err ))
325344 }
326- return p .store .Insert (ctx , tx , database.InsertRequest {Version : 0 })
327- }); err != nil {
328- // Mark the error as retryable so we can try again. It's possible that another instance
329- // is creating the table at the same time and the checks above will succeed on the next
330- // iteration.
331- return retry .RetryableError (fmt .Errorf ("failed to create version table: %w" , err ))
332345 }
346+
333347 return nil
334348 })
335349}
@@ -431,7 +445,6 @@ func (p *Provider) runGo(ctx context.Context, db database.DBTxConn, m *Migration
431445// runSQL is a helper function that runs the given SQL statements in the given direction. It must
432446// only be called after the migration has been parsed.
433447func (p * Provider ) runSQL (ctx context.Context , db database.DBTxConn , m * Migration , direction bool ) error {
434-
435448 if ! m .sql .Parsed {
436449 return fmt .Errorf ("sql migrations must be parsed" )
437450 }
0 commit comments