Skip to content

Commit 43a101a

Browse files
committed
fix: ensure migration progress is not lost for mysql
This is similar to #1966.
1 parent bb6d46a commit 43a101a

File tree

1 file changed

+29
-9
lines changed

1 file changed

+29
-9
lines changed

sqlx-core/src/mysql/migrate.rs

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::connection::ConnectOptions;
1+
use crate::connection::{ConnectOptions, Connection};
22
use crate::error::Error;
33
use crate::executor::Executor;
44
use crate::migrate::MigrateError;
@@ -209,29 +209,49 @@ CREATE TABLE IF NOT EXISTS _sqlx_migrations (
209209
migration: &'m Migration,
210210
) -> BoxFuture<'m, Result<Duration, MigrateError>> {
211211
Box::pin(async move {
212+
// Use a single transaction for the actual migration script and the essential bookeeping so we never
213+
// execute migrations twice. See https://github.com/launchbadge/sqlx/issues/1966.
214+
// The `execution_time` however can only be measured for the whole transaction. This value _only_ exists for
215+
// data lineage and debugging reasons, so it is not super important if it is lost. So we initialize it to -1
216+
// and update it once the actual transaction completed.
217+
let mut tx = self.begin().await?;
212218
let start = Instant::now();
213219

214-
let res = self.execute(&*migration.sql).await;
215-
216-
let elapsed = start.elapsed();
217-
218220
// language=MySQL
219221
let _ = query(
220222
r#"
221223
INSERT INTO _sqlx_migrations ( version, description, success, checksum, execution_time )
222-
VALUES ( ?, ?, ?, ?, ? )
224+
VALUES ( ?, ?, TRUE, ?, -1 )
223225
"#,
224226
)
225227
.bind(migration.version)
226228
.bind(&*migration.description)
227-
.bind(res.is_ok())
228229
.bind(&*migration.checksum)
230+
.execute(&mut tx)
231+
.await?;
232+
233+
let _ = tx.execute(&*migration.sql).await?;
234+
235+
tx.commit().await?;
236+
237+
// Update `elapsed_time`.
238+
// NOTE: The process may disconnect/die at this point, so the elapsed time value might be lost. We accept
239+
// this small risk since this value is not super important.
240+
241+
let elapsed = start.elapsed();
242+
243+
let _ = query(
244+
r#"
245+
UPDATE _sqlx_migrations
246+
SET execution_time = ?
247+
WHERE version = ?
248+
"#,
249+
)
229250
.bind(elapsed.as_nanos() as i64)
251+
.bind(migration.version)
230252
.execute(self)
231253
.await?;
232254

233-
res?;
234-
235255
Ok(elapsed)
236256
})
237257
}

0 commit comments

Comments
 (0)