@@ -30,18 +30,20 @@ func init() {
3030var DefaultMigrationsTable = "schema_migrations"
3131
3232var (
33- ErrDatabaseDirty = fmt .Errorf ("database is dirty" )
34- ErrNilConfig = fmt .Errorf ("no config" )
35- ErrNoDatabaseName = fmt .Errorf ("no database name" )
36- ErrAppendPEM = fmt .Errorf ("failed to append PEM" )
37- ErrTLSCertKeyConfig = fmt .Errorf ("to use TLS client authentication, both x-tls-cert and x-tls-key must not be empty" )
33+ ErrDatabaseDirty = fmt .Errorf ("database is dirty" )
34+ ErrNilConfig = fmt .Errorf ("no config" )
35+ ErrNoDatabaseName = fmt .Errorf ("no database name" )
36+ ErrAppendPEM = fmt .Errorf ("failed to append PEM" )
37+ ErrTLSCertKeyConfig = fmt .Errorf ("to use TLS client authentication, both x-tls-cert and x-tls-key must not be empty" )
38+ ErrInvalidIsolationLevel = fmt .Errorf ("invalid isolation level given in x-tx-isolation" )
3839)
3940
4041type Config struct {
4142 MigrationsTable string
4243 DatabaseName string
4344 NoLock bool
4445 StatementTimeout time.Duration
46+ TxIsolation sql.IsolationLevel
4547}
4648
4749type Mysql struct {
@@ -251,6 +253,15 @@ func (m *Mysql) Open(url string) (database.Driver, error) {
251253 }
252254 }
253255
256+ txIsolationParam := customParams ["x-tx-isolation" ]
257+ txIsolation := sql .LevelSerializable
258+ if txIsolationParam != "" {
259+ txIsolation , err = getIsolationLevel (txIsolationParam )
260+ if err != nil {
261+ return nil , err
262+ }
263+ }
264+
254265 db , err := sql .Open ("mysql" , config .FormatDSN ())
255266 if err != nil {
256267 return nil , err
@@ -261,6 +272,7 @@ func (m *Mysql) Open(url string) (database.Driver, error) {
261272 MigrationsTable : customParams ["x-migrations-table" ],
262273 NoLock : noLock ,
263274 StatementTimeout : time .Duration (statementTimeout ) * time .Millisecond ,
275+ TxIsolation : txIsolation ,
264276 })
265277 if err != nil {
266278 return nil , err
@@ -354,7 +366,7 @@ func (m *Mysql) Run(migration io.Reader) error {
354366}
355367
356368func (m * Mysql ) SetVersion (version int , dirty bool ) error {
357- tx , err := m .conn .BeginTx (context .Background (), & sql.TxOptions {Isolation : sql . LevelSerializable })
369+ tx , err := m .conn .BeginTx (context .Background (), & sql.TxOptions {Isolation : m . config . TxIsolation })
358370 if err != nil {
359371 return & database.Error {OrigErr : err , Err : "transaction start failed" }
360372 }
@@ -506,3 +518,26 @@ func readBool(input string) (value bool, valid bool) {
506518 // Not a valid bool value
507519 return
508520}
521+
522+ func getIsolationLevel (input string ) (sql.IsolationLevel , error ) {
523+ switch input {
524+ case "DEFAULT" :
525+ return sql .LevelDefault , nil
526+ case "READ-UNCOMMITTED" :
527+ return sql .LevelReadUncommitted , nil
528+ case "READ-COMMITTED" :
529+ return sql .LevelReadCommitted , nil
530+ case "WRITE-COMMITTED" :
531+ return sql .LevelWriteCommitted , nil
532+ case "REPEATABLE-READ" :
533+ return sql .LevelRepeatableRead , nil
534+ case "SNAPSHOT" :
535+ return sql .LevelSnapshot , nil
536+ case "SERIALIZABLE" :
537+ return sql .LevelSerializable , nil
538+ case "LINEARIZABLE" :
539+ return sql .LevelLinearizable , nil
540+ default :
541+ return sql .LevelSerializable , ErrInvalidIsolationLevel
542+ }
543+ }
0 commit comments