Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MySQL replication fixes #170

Merged
merged 17 commits into from
Jan 1, 2025
Merged

MySQL replication fixes #170

merged 17 commits into from
Jan 1, 2025

Conversation

rkistner
Copy link
Contributor

@rkistner rkistner commented Dec 31, 2024

Fixes some issues with MySQL replication:

Timestamps: Timezone handling

Timezone in timestamps were not handled correctly if the MySQL server is configured with a timezone other than UTC. The issue is that MySQL always returns timestamps in the session timezone, without any timezone indicator. So there is no way to know what we should configure the client timezone with if we don't know the server timezone.

The current tests also stored timestamps in the default/server timezone, but expected them to be returned in UTC timezone.

This changes:

  1. Fix the tests to use +00:00 timezone in literals.
  2. Always set the timezone on the mysql connection used for queries: SET time_zone = "+00:00". This does not appear to be needed for zongji.

Timestamps: Updates broken

When updating a row containing an update, the row was converted in-place to the SQLite format, then converted again. The first pass converted the timestamp to a string, then the second pass failed since it expected a Date. This results in an error row[key].toISOString is not a function.

This fixes the conversion to not modify the original row, and also avoids doing the conversion twice.

Timestamps: Handling invalid dates

With MySQL, it is possible to disable strict mode and then persist a timestamp such as 2024-00-00 00:00:00. This is not a valid Date in JavaScript, and results in an error RangeError: Invalid time value when calling toISOString().

This fixes the issue by converting these to null.

Initial replication: Improved error handling

The implementation of snapshot handling did not handle errors properly in all cases (such as the above issue) - it resulted in an unhandled promise rejection, which could cause either the process to crash, or replication to stall.

This changes the snapshot query to using a Readable stream, which does not have this issue.

Resuming replication

When replication is resumed after a restart, the list of tables were not loaded, resulting in an empty list of tables in includeSchema, and no changes replicated. This now loads the list of tables when resuming replication.

Quoting table names

This now properly quotes table names with backticks in snapshot queries, avoiding potential issues when a table name contains special characters for some reason. Unlike with Postgres, this is not required matching the table name case, but is still better to do either way.

Copy link

changeset-bot bot commented Dec 31, 2024

🦋 Changeset detected

Latest commit: 5666fb2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@powersync/service-module-mysql Patch
@powersync/service-image Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@rkistner rkistner marked this pull request as ready for review January 1, 2025 10:35
@rkistner rkistner merged commit cb749b9 into main Jan 1, 2025
15 checks passed
@rkistner rkistner deleted the mysql-fixes branch January 1, 2025 11:25
});
// MAX_EXECUTION_TIME(0) hint disables execution timeout for this query
const query = connection.query(`SELECT /*+ MAX_EXECUTION_TIME(0) */ * FROM ${escapeMysqlTableName(table)}`);
const stream = query.stream();
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a nice simplification to the streaming process! 🥳

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.

3 participants