Skip to content

MySQL: restore blocked column to BOOLEAN so IX_TXNO_OUTBOX_1 is usable - #1070

Open
andreib-goji wants to merge 1 commit into
gruelbox:masterfrom
andreib-goji:fix-mysql-boolean-literals
Open

andreib-goji wants to merge 1 commit into
gruelbox:masterfrom
andreib-goji:fix-mysql-boolean-literals

Conversation

@andreib-goji

@andreib-goji andreib-goji commented Jul 18, 2026

Copy link
Copy Markdown

Problem: migration 6 renamed blacklisted to blocked but also changed the MySQL column type from BOOLEAN to VARCHAR(250). Boolean comparisons against the VARCHAR need an implicit cast, so the retention cleanup DELETE can't use blocked as an index range condition on IX_TXNO_OUTBOX_1 and scans the whole processed = true region. Under REPEATABLE READ it next-key-locks every retained row it scans (even when it deletes nothin) and concurrent outbox writers hit lock wait timeouts.

Fix: migration 14 (MySQL dialects only) converts the column back to BOOLEAN. Existing "0"/"1" values convert in place. Queries keep boolean literals.

Tests:

  • TestMySqlDialect pins migration 14 SQL and boolean comparisons.
  • migration14ConvertsExistingBlockedValues rebuilds a populated v13 schema by replaying real migrations, then migrates and verifies type and semantics (MySQL 5 + 8).
  • retentionCleanupDoesNotLockRetainedRecords proves an idle cleanup transaction no longer blocks writes to retained rows. Passes on H2, MySQL 5/8, PostgreSQL 16, Oracle 21, SQL Server 2019.

@badgerwithagun badgerwithagun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @andreib-goji and thank you for your PR.

Looking at migration 6, I actually think this was an error in the PR that introduced the schema change. blocked shouldn't be a varchar. The correct change here will be to add a migration to return the column to the correct type (correctly migrating existing values) rather than work around it.

We also need an acceptance test (in https://github.com/gruelbox/transaction-outbox/blob/master/transactionoutbox-testing/src/main/java/com/gruelbox/transactionoutbox/testing/AbstractAcceptanceTest.java) to ensure the original issue is resolved on all dialects. You need to replicate the failed blocking symptoms there before applying your fix.

Migration 6 renamed blacklisted to blocked but also changed the MySQL
column type from BOOLEAN to VARCHAR(250). Comparing a VARCHAR against
a boolean needs an implicit cast, so the retention cleanup DELETE
cannot use blocked as an index range condition on IX_TXNO_OUTBOX_1
and scans the whole processed = true region. Under REPEATABLE READ it
next-key-locks every retained row it scans - even when it deletes
nothing - and concurrent outbox writers hit lock wait timeouts.

Migration 14 converts the column back to BOOLEAN; existing "0"/"1"
values convert in place. Covered by dialect SQL tests, a conversion
test that migrates a populated v13 schema, and an acceptance test
proving an idle cleanup transaction no longer blocks writes to
retained rows.
@andreib-goji
andreib-goji force-pushed the fix-mysql-boolean-literals branch from 19a915e to 2504122 Compare July 24, 2026 08:25
@andreib-goji andreib-goji changed the title MySQL: compare blocked with '0' instead of boolean literal so IX_TXNO_OUTBOX_1 is usable MySQL: restore blocked column to BOOLEAN so IX_TXNO_OUTBOX_1 is usable Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants