{"record":{"id":"6bc2cd36b897c762","repo":"apache/seatunnel","slug":"tables-were-locked-explicitly-but-to-get-a-consis","errorCode":null,"errorMessage":"Tables were locked explicitly, but to get a consistent snapshot we cannot release the locks until we've read all tables.","messagePattern":"Tables were locked explicitly, but to get a consistent snapshot we cannot release the locks until we've read all tables\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"seatunnel-connectors-v2/connector-cdc/connector-cdc-mysql/src/main/java/io/debezium/connector/mysql/MySqlSnapshotChangeEventSource.java","lineNumber":265,"sourceCode":"\n    @Override\n    protected void releaseSchemaSnapshotLocks(\n            RelationalSnapshotContext<MySqlPartition, MySqlOffsetContext> snapshotContext)\n            throws SQLException {\n        if (connectorConfig.getSnapshotLockingMode().usesMinimalLocking()) {\n            if (isGloballyLocked()) {\n                globalUnlock();\n            }\n            if (isTablesLocked()) {\n                // We could not acquire a global read lock and instead had to obtain individual\n                // table-level read locks\n                // using 'FLUSH TABLE <tableName> WITH READ LOCK'. However, if we were to do this,\n                // the 'UNLOCK TABLES'\n                // would implicitly commit our active transaction, and this would break our\n                // consistent snapshot logic.\n                // Therefore, we cannot unlock the tables here!\n                // https://dev.mysql.com/doc/refman/5.7/en/flush.html\n                LOGGER.warn(\n                        \"Tables were locked explicitly, but to get a consistent snapshot we cannot release the locks until we've read all tables.\");\n            }\n        }\n    }\n\n    @Override\n    protected void releaseDataSnapshotLocks(\n            RelationalSnapshotContext<MySqlPartition, MySqlOffsetContext> snapshotContext)\n            throws Exception {\n        if (isGloballyLocked()) {\n            globalUnlock();\n        }\n        if (isTablesLocked()) {\n            tableUnlock();\n            if (!delayedSchemaSnapshotTables.isEmpty()) {\n                schemaEvents.clear();\n                createSchemaEventsForTables(snapshotContext, delayedSchemaSnapshotTables, false);\n","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-cdc/connector-cdc-mysql/src/main/java/io/debezium/connector/mysql/MySqlSnapshotChangeEventSource.java#L247-L283","documentation":"When the snapshot could not obtain a global read lock (FLUSH TABLES WITH READ LOCK) and instead locked tables explicitly (LOCK TABLES), releasing locks via UNLOCK TABLES would implicitly commit the active transaction that holds the consistent-snapshot read view. Debezium therefore deliberately skips unlocking and warns that locks are held until all tables are read.","triggerScenarios":"releaseSchemaSnapshotLocks runs and lockTables was true — i.e. the global read lock failed so the source fell back to per-table explicit locks, and UNLOCK TABLES was suppressed to preserve snapshot consistency.","commonSituations":"MySQL 8.0.32+/managed clouds where FLUSH TABLES WITH READ LOCK requires privileges the CDC user lacks; large schemas where the explicit-lock fallback is exercised; operators seeing locks held long on big snapshots and wondering why they aren't released.","solutions":["Grant the connector user privileges to take a global read lock (RELOAD + FLUSH_TABLES) so the explicit-lock fallback is not used","Use snapshot.mode with a consistent snapshot mechanism (e.g. schema-only or when_needed with GTID) orDebezium's incremental snapshot to avoid long locks","Ensure the snapshot completes promptly — keep the window between lock and unlock small; monitor for stuck snapshots","If the warning appears after a completed snapshot, verify the history topic recorded all tables; run a new snapshot if the history is incomplete"],"exampleFix":"// before\nconnectorConfig.snapshotLockingMode(SnapshotLockingMode.MINIMAL)\n// after (use extended locking so a consistent global lock is taken, avoiding the explicit-lock fallback)\nconnectorConfig.snapshotLockingMode(SnapshotLockingMode.EXTENDED)","handlingStrategy":"validation","validationCode":"// Ensure the connector user can take a global read lock so the explicit-lock fallback is avoided:\n// SHOW GRANTS FOR 'cdc_user'@'%';\n// -- must include RELOAD (and FLUSH_TABLES on MySQL 8) for FLUSH TABLES WITH READ LOCK","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Grant RELOAD/FLUSH_TABLES to the CDC user to avoid explicit table locks","Prefer incremental snapshot mode to minimize lock duration","Keep snapshots fast: adequate memory and network to the source","Alert on long-held table locks during snapshot phase"],"tags":["mysql","cdc","snapshot","locking"],"backgroundTag":"internal-invariant-violation","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}