From aef2d7c861964d018aff72b7c9b90faf13c1ddfc Mon Sep 17 00:00:00 2001 From: Joakim Carlstein Date: Wed, 29 May 2024 15:06:10 +0200 Subject: [PATCH] fix(mysql): handle table initialization better in clustered database environments The CREATE TABLE IF NOT EXISTS yields more locks than checking if the table exists using a SELECT first before running CREATE TABLE. This makes more sense as the table usually already exists, so we optimize for the happy path. --- .changeset/thirty-beds-fetch.md | 5 +++++ packages/mysql/src/index.ts | 19 ++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 .changeset/thirty-beds-fetch.md diff --git a/.changeset/thirty-beds-fetch.md b/.changeset/thirty-beds-fetch.md new file mode 100644 index 0000000..9819f69 --- /dev/null +++ b/.changeset/thirty-beds-fetch.md @@ -0,0 +1,5 @@ +--- +'@emigrate/mysql': patch +--- + +Avoid "CREATE TABLE IF NOT EXISTS" as it's too locking in a clustered database when running it concurrently diff --git a/packages/mysql/src/index.ts b/packages/mysql/src/index.ts index cc659e6..2a1354e 100644 --- a/packages/mysql/src/index.ts +++ b/packages/mysql/src/index.ts @@ -156,9 +156,26 @@ const deleteMigration = async (pool: Pool, table: string, migration: MigrationMe }; const initializeTable = async (pool: Pool, table: string) => { + const [result] = await pool.execute({ + sql: ` + SELECT + 1 as table_exists + FROM + information_schema.tables + WHERE + table_schema = DATABASE() + AND table_name = ? + `, + values: [table], + }); + + if (result[0]?.['table_exists']) { + return; + } + // This table definition is compatible with the one used by the immigration-mysql package await pool.execute(` - CREATE TABLE IF NOT EXISTS ${escapeId(table)} ( + CREATE TABLE ${escapeId(table)} ( name varchar(255) not null primary key, status varchar(32), date datetime not null