uptrace / bun

SQL-first Golang ORM
https://bun.uptrace.dev
BSD 2-Clause "Simplified" License
3.69k stars 228 forks source link

bun migrations locks #758

Open alos0 opened 1 year ago

alos0 commented 1 year ago

This implementation has a disadvantage https://github.com/uptrace/bun/blob/master/migrate/migrator.go#L385-L406: IF pod fails during migration, lock still is active. After pod reboot pod can't continue migration because of lock.

Our WA: 1) Lock is in separate connection in separate transaction 2) We don't commit changes but we rollback it in defer function (If connection fails or pod reboots postgres automatically rollbacks all changes and no lock after reboot) var bunMigrationsTable = "bun_migrations"

var bunLockMigrationTable = "bun_migration_locks"

var bunLockMigrationColumn = "table_name"

var bunInsertLockQuery =insert into "+ bunLockMigrationTable +"("+ bunLockMigrationColumn +") values('+ bunMigrationsTable +')`

` lockConn, err := s.DbProvider.GetConn(ctx)

if err != nil {  

    log.ErrorC(ctx, "Error during getting lock connection")  

    return gerrors.WrapPrefix(err, "error during getting lock connection", 0)  

}  

defer lockConn.Close()  

lockTx, err := lockConn.BeginTx(ctx, nil)  

if err != nil {  

    log.ErrorC(ctx, "Error during beginning lock transaction")  

    return gerrors.WrapPrefix(err, "error during beginning lock transaction", 0)  

}  

defer lockTx.Rollback()  

_, err = lockTx.Exec(bunInsertLockQuery)  

`

PS Firstly I tried to use as in example. Put lock exactly before migrator.Migrate and then faced with lock on table

iglin commented 1 year ago

Hi all! Speaking of using locks in migrations, I wonder, do clients of the library really have to implement their own locking mechanism? Why does not library provide locking inside its logic - it is typical task for everyone migrating databases.

vmihailenco commented 1 year ago

Why does not library provide locking inside its logic - it is typical task for everyone migrating databases.

You must manually call lock and unlock which enables function composition, for example, here is how we implemented database reset in Uptrace.

Lock is in separate connection in separate transaction

I am not sure this will work, but you are welcome to try. Just make sure it works for Postgres, MySQL, and MSSQL.