feat(db): remove the hardcoded --server-id=0 parameter from MySQL startup, fixes #6768#7608
Conversation
|
Previous attempt to do something similar: |
|
I repoen again as this solution is simpler. |
stasadev
left a comment
There was a problem hiding this comment.
It does look simpler, and requires a push for Docker images from our side. (I'll do it.)
It needs some addition to the documentation, doesn't it?
|
Agree, can you give some advice on where you want to mention this env variable and I will add it. |
|
I wonder if it would be better to just remove the command line arg for |
|
| # Oracle mysql 5.7+ deprecates mysql_install_db | ||
| if [ "${mysqld_version}" = "5.7" ] || [[ "${mysqld_version%%%.*}" =~ ^8.[04]$ ]]; then | ||
| mysqld --defaults-file=/var/tmp/my.cnf --initialize-insecure --datadir=${DATADIR:-/var/lib/mysql} --server-id=0 | ||
| mysqld --defaults-file=/var/tmp/my.cnf --initialize-insecure --datadir=${DATADIR:-/var/lib/mysql} --server-id=${MYSQL_SERVER_ID:-0} |
There was a problem hiding this comment.
create_base_db.sh is called during building ddev-dbserver (on our side, not on the user's side), so MYSQL_SERVER_ID is never going to be used here.
The only relevant change in docker-entrypoint.sh, right?
There was a problem hiding this comment.
Agreed, this usage doesn't need the --server-id=${MYSQL_SERVER_ID}
That's an interesting idea, but I don't know the answer. |
|
I would not mind removing it instead. Mysql defaults to 1 that is much better than 0. But wonder about historical reason to set it, as its pretty odd. |
|
”MySQL 5.7: server_id default is 0. If binary logging is enabled, you must set a non-zero server_id or the server won’t start; and with server_id=0, a source/replica refuses replication connections. MySQL 8.0+: default changed to 1 (part of broader default changes). It still must be unique in any replication topology.” |
|
IIRC the server_id is only for replication, which would be really unusual in a local dev environment. Am I wrong? |
|
Oh, reading the OP... you do want to set up replication. Can you say a bit about what's inspiring you to think about replication? |
|
Its in the PR description, I have learned from other attempts to include it :) "Using packages that require MySQL replication, such as laravel-trigger which provides MySQL event subscribers based on MySQL replication So all other settings is possible to fix . But the hardcoded --server-id=0 blocks me So its not standard replication, as that would not make so much sense. Its more about consuming the data from the replication stream to dispatch laravel jobs based on changes in db. |
I need to override this locally for the same reasons as OP - development/testing for production. Perhaps the test suite could be run after removing the cli flag and see what happens? If it works, maybe its best to just remove it |
rfay
left a comment
There was a problem hiding this comment.
There's nothing wrong with this; just needs to do a little bit less and have some documentation.
How about a guest blog to ddev.com explaining how to do replication with mysql8.x ?
| # Oracle mysql 5.7+ deprecates mysql_install_db | ||
| if [ "${mysqld_version}" = "5.7" ] || [[ "${mysqld_version%%%.*}" =~ ^8.[04]$ ]]; then | ||
| mysqld --defaults-file=/var/tmp/my.cnf --initialize-insecure --datadir=${DATADIR:-/var/lib/mysql} --server-id=0 | ||
| mysqld --defaults-file=/var/tmp/my.cnf --initialize-insecure --datadir=${DATADIR:-/var/lib/mysql} --server-id=${MYSQL_SERVER_ID:-0} |
There was a problem hiding this comment.
Agreed, this usage doesn't need the --server-id=${MYSQL_SERVER_ID}
| fi | ||
| echo "Starting mysqld --skip-networking --socket=${MYSQL_UNIX_PORT}" | ||
| mysqld --defaults-file=/var/tmp/my.cnf --user=root --socket=${MYSQL_UNIX_PORT} --innodb_log_file_size=48M --skip-networking --datadir=${DATADIR:-/var/lib/mysql} --server-id=0 --skip-log-bin & | ||
| mysqld --defaults-file=/var/tmp/my.cnf --user=root --socket=${MYSQL_UNIX_PORT} --innodb_log_file_size=48M --skip-networking --datadir=${DATADIR:-/var/lib/mysql} --server-id=${MYSQL_SERVER_ID:-0} --skip-log-bin & |
| echo "Starting mysqld." | ||
| tail -f /var/log/mysqld.log ${DATADIR:-/var/lib/mysql}/mysqld.err & | ||
| exec mysqld --server-id=0 | ||
| exec mysqld --server-id=${MYSQL_SERVER_ID:-0} |
There was a problem hiding this comment.
This is the only one that matters. Of course, needs docs on how it's to be used and why and when.
There was a problem hiding this comment.
Great, will fix first thing tomorrow.
| MYSQL_SERVER_ID=1 | ||
| ``` | ||
|
|
||
| **Note:** Command-line arguments take precedence over configuration files, so you cannot override the server ID through custom `.cnf` files in `.ddev/mysql/`. The environment variable approach is required. |
There was a problem hiding this comment.
Can I suggest adding something that explains why only server-id needs to have a cli arg that requires being changed by env var, while everything else can be done with cnf? It's still not clear to me and surely causes confusion for anyone who comes across it (including the maintainers, apparently).
The closest I've seen to an explanation is this
MySQL 5.7: server_id default is 0. If binary logging is enabled, you must set a non-zero server_id or the server won’t start; and with server_id=0, a source/replica refuses replication connections.
MySQL 8.0+: default changed to 1 (part of broader default changes). It still must be unique in any replication topology
I don't see why the overridable defaults aren't sufficient.
Even "we don't actually know why this is here, but we're keeping it for safety's sake, so the env var is needed" would be better than nothing.
There was a problem hiding this comment.
I agree that the cleanest solution is probably to remove --server-id=0, but seems like its a riskier operation? I am open for any suggestion, as long as it does not delay the actual possibility to change server id. And as I understand it might be a too risky change right now. While ENV is 100% backward compatible.
There was a problem hiding this comment.
My impression was that ddev's extension test suite was meant to allow for making such changes and testing for breakage. If there isn't a test for it, either one should be added (which would require understanding the actual purpose for it) or maybe it wasn't important to begin with
|
Download the artifacts for this pull request:
See Testing a PR. |
|
I have tested the functionality now with the new build, and it works good. Step 1. Step 2. Step 3. Step 4. Step 5. Let me know if you want me to test something more. I will continue to config my environment based on this artifacts, and if there is something useful to share regarding how I use the replication in laravel I will try to share something. Will at least make sure it runs as expected and share some info. |
|
I don't understand what replication has to do with laravel, but am sure interested in your experimentation. Can you say more? Replication should be completely transparent to Laravel, true? |
|
For normal replication as in master -> slave it is of course transparent to laravel. But in my case laravel runs a long running process (package https://github.com/huangdijia/laravel-trigger) so laravel becomes the slave and listens to all updates in database. So I can define what tables and what type of events is interesting, and then I can dispatch events/jobs in laravel based on "realtime" actions in database. But can try to show something.. still in process to configure the last bits. |
|
Super interesting! So this really isn't an actual "Laravel" thing, but rather a very specific extra technique. Looking forward to hearing more! |
|
Moved to draft pending manual testing and discussion. |
|
@rfay congrats on latest release! Is it possible to rebase and create new artifacts based on latest version just released? So I can continue testing based on latest version? |
|
I'll do rebase with push shortly. |
2dd6039 to
8f5e415
Compare
|
@cyppe, done, run this to pull new images after switching the binary: |
Thank you! |
|
Will do! A bit busy for a couple of days now, but will be finished during next week for sure. Will be pretty quick to test, as basically either both mariadb and mysql starts with default value or not. And then it should be possible to override default in the custom cnf file. And then how everyone chooses to use this possibility is probably up to the users. So I agree, we should avoid replication specific test cases as that is more of a possibility enabled by this change. But as replication is in my own interest I will for sure test it and let you know how it works out. But will report back in a couple of days according to your list. |
|
Took a moment now anyway and did all the relevant tests. Tested old + new version of both MySQL and MariaDB as we expect old to get default server id = 0, and new versions to get server id = 1. And it works. And I updated PR description a few days ago, so its up to date as I see it. UPDATE: Actually found a typo in docs + my PR description example where I wrote server_id in the custom cnf file, but it should be server-id. Updated both now. MariaDB 11.4Configuration: database:
type: mariadb
version: 11.4Test Cases1. Default ConfigurationQuery: SELECT @@server_id;Expected: 2. Custom ConfigurationConfiguration file: [mysqld]
server-id = 2Query: SELECT @@server_id;Expected: MariaDB 5.5Configuration: database:
type: mariadb
version: 5.5Test Cases1. Default ConfigurationQuery: SELECT @@server_id;Expected: 2. Custom ConfigurationConfiguration file: [mysqld]
server-id = 2Query: SELECT @@server_id;Expected: MySQL 5.7Configuration: database:
type: mysql
version: 5.7Test Cases1. Default ConfigurationQuery: SELECT @@server_id;Expected: 2. Custom ConfigurationConfiguration file: [mysqld]
server-id = 2Query: SELECT @@server_id;Expected: MySQL 8.4Configuration: database:
type: mysql
version: 8.4Test Cases1. Default ConfigurationQuery: SELECT @@server_id;Expected: 2. Custom ConfigurationConfiguration file: [mysqld]
server-id = 2Query: SELECT @@server_id;Expected: |
21c9210 to
43ff377
Compare
|
Rebased and moved to ready to review. Time to test with the suggested techniques of @cyppe . @nickchomey since you're super interested could you do manual testing as well? |
|
Gladly! I'll try to check it out sometime today. |
stasadev
left a comment
There was a problem hiding this comment.
Looks good to me, thank you for this simplification.
I tested it with MySQL 8.0 and MariaDB 11.8.
I checked the actual value with:
ddev mysql -e 'SELECT @@server_id;'Now it uses the default when not set (as expected) and updates on modification in .ddev/mysql/*.cnf.
|
I only tried mariadb 11.4 and it is fine for me. I suspect if there might be any issues, they'd be related to old versions of mysql. |
rfay
left a comment
There was a problem hiding this comment.
Congrats! As far as I can tell this involves no risk at all and will enable people to do some new and interesting things like you're doing.
Simplify MySQL Server ID Configuration
Summary
This PR removes the hardcoded
--server-id=0parameter from MySQL startup, allowing users to configure the server ID through standard MySQL configuration files in.ddev/mysql/.Problem
Currently, ddev hardcodes
--server-id=0in the MySQL startup command, which prevents users from configuring MySQL replication. Command-line arguments take precedence over configuration files, so it's not possible to override the server ID through custom MySQL.cnffiles placed in.ddev/mysql/.According to MySQL documentation: "If the server ID is set to 0, binary logging takes place, but a source with a server ID of 0 refuses any connections from replicas, and a replica with a server ID of 0 refuses to connect to a source."
This limitation prevents developers from:
Solution
--server-id=0fromdocker-entrypoint.shDatabase Version Defaults
When no server-id is explicitly configured, different database versions have different default behaviors:
MariaDB:
server_id = 1server_id = 0MySQL:
server_id = 1server_id = 0References:
Usage
Users can now set a custom server ID using standard MySQL configuration:
Create
.ddev/mysql/server-id.cnf:Then run
ddev restartto apply the configuration.Benefits of This Approach
Use Case Example
This change enables developers to use MySQL replication functionality in their ddev development environment. Applications requiring MySQL replication can now use:
.ddev/mysql/replication.cnf:With this PR, developers can configure MySQL replication settings locally, matching their production MySQL replication setup using standard MySQL configuration practices.