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

Symfony 6 / Doctrine / Migration: [ERROR] The database schema is not in sync with the current mapping file #6091

Closed
henritielscher opened this issue Jul 11, 2023 · 24 comments
Labels

Comments

@henritielscher
Copy link

Hey there I described my issue in Stack Overflow HERE in detail. I hope it is fine to not write it down again...

I use the dbal version 3.6.3

Huge thanks in advance and please let me know if this is helpful enough to determine the problem...
I'm going insane over this and have no idea where to get further informations :(

@derrabus
Copy link
Member

StackOverflow is a good place for your kind of question. Alternatively, you could also try to ask for help on https://github.com/doctrine/orm/discussions/.

This issue tracker however is used for bug reports and feature request, which is why I'm closing your issue.

I've read your write-up on StackOverflow however, but I don't really know why the schema validation fails in your case. My best guess would be that the old MariaDB version on your prod system behaves a bit differently than the fairly recent version on your dev system. But that's a shot in the dark. 😕

@derrabus derrabus closed this as not planned Won't fix, can't repro, duplicate, stale Jul 12, 2023
@henritielscher
Copy link
Author

Thanks @derrabus.
And sorry, for making this an issue. I also think it has to be something related to the production MariaDB, because like mentioned in my question on SO, the weirdest thing is, that when I dump the full schema into one migration it does not consider MariaDB as platform although it is configured as default. I try the discussion link. Thanks again :)

@greg0ire
Copy link
Member

One odd thing happened when I wiped all migrations and dumped it into one on the server. It suddenly used the MySQL platform over the MariaDB platform which is weird since I defined the platform in the config and I'm running MariaDB as well.

I don't fully understand what you mean by this. How do you know which platform the DBAL uses internally when using this or that command?

I build an App in Symfony 6.2 and have it running on a Raspberry Pi. Here are the prerequisites:

Why are you using different versions of MariaDB? Isn't that looking for trouble?

@henritielscher
Copy link
Author

Hello, @greg0ire.
I used the doctrine:migrations:dump-schema command on my staging and my development environment and checked the corresponding migration files. The difference was that my development dump was checking for the MariaDBPlatform and on staging it was checking for MySQL.

And yes, you are correct. That was a dumb decision I now regret, but I'm fairly new and did not consider this to be a huge problem in the first place, since the documentation states that all MariaDB versions up from version 10.2. are supported.

@greg0ire
Copy link
Member

Might be cool to use bin/console debug:config doctrine to check if there is any difference in configuration between your envs that would explain this.

@henritielscher
Copy link
Author

henritielscher commented Jul 15, 2023

Thanks @greg0ire :) But unfortunately that brought the same results.
I also updated both of my DBs on dev and prod to the same version...

Now I wonder why doctrine:migrations:sync-metadata-storage basically does nothing?
I have the same migration files and if I manually delete the doctrine_migration_versions table, it recreates it without any entries.

Also when I run doctrine:schema:validate with verbose, it shows me the following queries which then after executing with doctrine:schema:update --force --complete also makes no difference :/

ALTER TABLE vendor CHANGE updated_at updated_at DATETIME(6) DEFAULT NULL COMMENT '(DC2Type:datetime_immutable)', CHANGE last_name last_name VARCHAR(255) DEFAULT NULL, CHANGE alternative_emails alternative_emails LONGTEXT DEFAULT NULL COMMENT '(DC2Type:simple_array)', CHANGE paypal paypal VARCHAR(255) DEFAULT NULL, CHANGE brand brand VARCHAR(255) DEFAULT NULL, CHANGE website website VARCHAR(255) DEFAULT NULL, CHANGE main_category main_category VARCHAR(255) DEFAULT NULL; ALTER TABLE market CHANGE updated_at updated_at DATETIME(6) DEFAULT NULL COMMENT '(DC2Type:datetime_immutable)', CHANGE info_facebook_event info_facebook_event VARCHAR(255) DEFAULT NULL, CHANGE banned_submissions banned_submissions LONGTEXT DEFAULT NULL COMMENT '(DC2Type:simple_array)'; ALTER TABLE submission CHANGE main_category main_category VARCHAR(255) DEFAULT NULL, CHANGE updated_at updated_at DATETIME(6) DEFAULT NULL COMMENT '(DC2Type:datetime_immutable)', CHANGE color_code color_code VARCHAR(255) DEFAULT NULL, CHANGE vendor_last_name vendor_last_name VARCHAR(255) DEFAULT NULL, CHANGE vendor_paypal vendor_paypal VARCHAR(255) DEFAULT NULL, CHANGE vendor_brand vendor_brand VARCHAR(255) DEFAULT NULL, CHANGE vendor_website vendor_website VARCHAR(255) DEFAULT NULL, CHANGE assignment_designation assignment_designation VARCHAR(255) DEFAULT NULL, CHANGE assignment_table_id assignment_table_id VARCHAR(255) DEFAULT NULL, CHANGE assignment_table_position assignment_table_position VARCHAR(255) DEFAULT NULL, CHANGE status_screening status_screening VARCHAR(255) DEFAULT 'unseen' NOT NULL; ALTER TABLE comment CHANGE author author VARCHAR(255) DEFAULT NULL; ALTER TABLE mail CHANGE created_at created_at DATETIME(6) DEFAULT NULL COMMENT '(DC2Type:datetime_immutable)';

I can't read anything different than already reflected in my entities.

@henritielscher
Copy link
Author

Even after dropping the schema entirely and creating a new one, it's still validating as not in sync with the current mapping file. That normally should not be the case, right?! Any ideas what this could cause?

@greg0ire
Copy link
Member

Now I wonder why doctrine:migrations:sync-metadata-storage basically does nothing?
I have the same migration files and if I manually delete the doctrine_migration_versions table, it recreates it without any entries.

I think you're misunderstanding what this command does. Please confirm that doctrine/migrations#1339 helps.

@greg0ire
Copy link
Member

greg0ire commented Jul 16, 2023

Also when I run doctrine:schema:validate with verbose, it shows me the following queries which then after executing with doctrine:schema:update --force --complete also makes no difference :/

Before looking into that, I would try to make sure the same platform is detected on all envs. Until that is fixed, there is little point running other commands and getting more confused

The difference was that my development dump was checking for the MariaDBPlatform and on staging it was checking for MySQL.

prod, as well, right?

Here is the line from which the platform is obtained: https://github.com/doctrine/migrations/blob/478fd2f2739fd3fd732b83eb729a51e7b32c2b99/lib/Doctrine/Migrations/DependencyFactory.php#L424

@henritielscher
Copy link
Author

henritielscher commented Jul 16, 2023

I think you're misunderstanding what this command does. Please confirm that doctrine/migrations#1339 helps.

Yes, that would very much help. I found little documentation about this and ended up asking ChatGPT 🤣

prod, as well, right?

Prod and staging are on the same server, so yes.

Here is the line from which the platform is obtained: https://github.com/doctrine/migrations/blob/478fd2f2739fd3fd732b83eb729a51e7b32c2b99/lib/Doctrine/Migrations/DependencyFactory.php#L424

I will dig further into this. Thanks a lot for your help! :)

@henritielscher
Copy link
Author

henritielscher commented Jul 16, 2023

Yep, so for whatever reason it seems to think that my prod / staging platform is of class MySQLPlatform. I put in a dd($this->getDependencyFactory()->getConnection()->getDatabasePlatform()); into the MigrateCommand.

Doctrine\DBAL\Platforms\MySQLPlatform^ {#528 #doctrineTypeMapping: null #doctrineTypeComments: null #_eventManager: Symfony\Bridge\Doctrine\ContainerAwareEventManager^ {#480 -listeners: [] -listeners: [] -subscribers: array:3 [ 0 => "doctrine.orm.listeners.doctrine_dbal_cache_adapter_schema_subscriber" 1 => "doctrine.orm.listeners.doctrine_token_provider_schema_subscriber" 2 => array:2 [ 0 => array:1 [ 0 => "loadClassMetadata" ] 1 => "doctrine.orm.default_listeners.attach_entity_listeners" ] ] -initialized: [] -initializedSubscribers: false -methods: [] -container: Symfony\Component\DependencyInjection\Argument\ServiceLocator^ {#458 -externalId: null -container: null -factories: array:3 [ "doctrine.orm.default_listeners.attach_entity_listeners" => array:4 [ 0 => "privates" 1 => "doctrine.orm.default_listeners.attach_entity_listeners" 2 => "getDoctrine_Orm_DefaultListeners_AttachEntityListenersService" 3 => true ] "doctrine.orm.listeners.doctrine_dbal_cache_adapter_schema_subscriber" => array:4 [ 0 => "privates" 1 => "doctrine.orm.listeners.doctrine_dbal_cache_adapter_schema_subscriber" 2 => "getDoctrine_Orm_Listeners_DoctrineDbalCacheAdapterSchemaSubscriberService" 3 => true ] "doctrine.orm.listeners.doctrine_token_provider_schema_subscriber" => array:4 [ 0 => "privates" 1 => "doctrine.orm.listeners.doctrine_token_provider_schema_subscriber" 2 => "getDoctrine_Orm_Listeners_DoctrineTokenProviderSchemaSubscriberService" 3 => true ] ] -loading: [] -factory: Container1jGAK7K\App_KernelStagingDebugContainer::getService(string|false $registry, string $id, ?string $method, string|bool $load): mixed^ {#67 returnType: "mixed" this: Container1jGAK7K\App_KernelStagingDebugContainer {#92 …} } -serviceMap: array:3 [ "doctrine.orm.default_listeners.attach_entity_listeners" => array:4 [ 0 => "privates" 1 => "doctrine.orm.default_listeners.attach_entity_listeners" 2 => "getDoctrine_Orm_DefaultListeners_AttachEntityListenersService" 3 => true ] "doctrine.orm.listeners.doctrine_dbal_cache_adapter_schema_subscriber" => array:4 [ 0 => "privates" 1 => "doctrine.orm.listeners.doctrine_dbal_cache_adapter_schema_subscriber" 2 => "getDoctrine_Orm_Listeners_DoctrineDbalCacheAdapterSchemaSubscriberService" 3 => true ] "doctrine.orm.listeners.doctrine_token_provider_schema_subscriber" => array:4 [ 0 => "privates" 1 => "doctrine.orm.listeners.doctrine_token_provider_schema_subscriber" 2 => "getDoctrine_Orm_Listeners_DoctrineTokenProviderSchemaSubscriberService" 3 => true ] ] -serviceTypes: array:3 [ "doctrine.orm.default_listeners.attach_entity_listeners" => "?" "doctrine.orm.listeners.doctrine_dbal_cache_adapter_schema_subscriber" => "?" "doctrine.orm.listeners.doctrine_token_provider_schema_subscriber" => "?" ] } } #_keywords: null

@greg0ire
Copy link
Member

Do you reproduce that behavior in dev when using --env=prod or --env=staging?

@henritielscher
Copy link
Author

Just did and it's showing me MariaDBPlatform with the staging settings on dev as well. Of course I changed the credentials to the local DB.

@greg0ire
Copy link
Member

I'm curious whether you enter this if block or not:

dbal/src/Connection.php

Lines 316 to 317 in 1c462ee

$this->platform = $this->detectDatabasePlatform();
$this->platform->setEventManager($this->_eventManager);

I want to make sure that the server_version you specified is taken into account on all envs.

@henritielscher
Copy link
Author

Oh, good point. I actually get into this block on ALL three envs. So platform is null every time.

@greg0ire
Copy link
Member

Ok well… debug further… what's the value of $params on this line:

$params = self::parseDatabaseUrl($params);
?

@henritielscher
Copy link
Author

The DriverManager seems to get the correct params in all three environments:

$params = [
  "dbname" => "<mydbname>"
  "host" => "127.0.0.1"
  "user" => "<mydbuser>"
  "password" => "<mydbpw>"
  "charset" => "utf8mb4"
  "driver" => "pdo_mysql"
  "port" => null
  "driverOptions" => array:1 [
    "platform" => "mariadb"
  ]
  "serverVersion" => "mariadb-11.0.2"
  "defaultTableOptions" => []
];

The result is coming from the argument passed and also when it's parsed.
I'm guessing everything is passed correctly then? So it is something on my system and I have to check on something on the database configuration...?

@greg0ire
Copy link
Member

greg0ire commented Jul 16, 2023

@henritielscher I'm sorry, apparently this blog is supposed to always be entered:

dbal/src/Connection.php

Lines 316 to 317 in 1c462ee

$this->platform = $this->detectDatabasePlatform();
$this->platform->setEventManager($this->_eventManager);

What's import to determine is whether this one is:

dbal/src/Connection.php

Lines 438 to 441 in 1c462ee

// Explicit platform version requested (supersedes auto-detection).
if (isset($this->params['serverVersion'])) {
return $this->params['serverVersion'];
}

If it is, this is the piece of code you will want to debug:

public function createDatabasePlatformForVersion($version)
{
$mariadb = stripos($version, 'mariadb') !== false;
if ($mariadb && version_compare($this->getMariaDbMysqlVersionNumber($version), '10.2.7', '>=')) {
return new MariaDb1027Platform();
}
if (! $mariadb) {
$oracleMysqlVersion = $this->getOracleMysqlVersionNumber($version);
if (version_compare($oracleMysqlVersion, '8', '>=')) {
if (! version_compare($version, '8.0.0', '>=')) {
Deprecation::trigger(
'doctrine/orm',
'https://github.com/doctrine/dbal/pull/5779',
'Version detection logic for MySQL will change in DBAL 4. '
. 'Please specify the version as the server reports it, e.g. "8.0.31" instead of "8".',
);
}
return new MySQL80Platform();
}
if (version_compare($oracleMysqlVersion, '5.7.9', '>=')) {
if (! version_compare($version, '5.7.9', '>=')) {
Deprecation::trigger(
'doctrine/orm',
'https://github.com/doctrine/dbal/pull/5779',
'Version detection logic for MySQL will change in DBAL 4. '
. 'Please specify the version as the server reports it, e.g. "5.7.40" instead of "5.7".',
);
}
return new MySQL57Platform();
}
}
Deprecation::trigger(
'doctrine/dbal',
'https://github.com/doctrine/dbal/pull/5060',
'MySQL 5.6 support is deprecated and will be removed in DBAL 4.'
. ' Consider upgrading to MySQL 5.7 or later.',
);
return $this->getDatabasePlatform();
}

@henritielscher
Copy link
Author

henritielscher commented Jul 16, 2023

Thanks again for your help. I really appreciate that someone can help me with this :)
So I tried it on dev and staging. In dev it jumps into the server-version block, but it in staging it ends here...

https://github.com/doctrine/dbal/blob/1c462eed54dcf6b33b7d39d6e60c390c279c57b2/src/Connection.php#L433C52-L436

@greg0ire
Copy link
Member

And what is the class of $this->_driver, in both cases?

@henritielscher
Copy link
Author

Sorry, I actually looked that up and totally forgot to mention...
In dev it is: Symfony\Bridge\Doctrine\Middleware\Debug\Driver

In staging it is: Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingDriverForV32
In contrast here the driver above is a decorated driver class here. But anyway that brings us a step closer I think.

I will hopefully manage to get into this asap.

@greg0ire
Copy link
Member

Interesting. If you run composer outdated, does any Sentry-related stuff come up?

@henritielscher
Copy link
Author

Ok, I finally had time to work on the project again, and f**k it really was the Sentry library that needed an update. Sentry is turned off on development, hence I didn't notice.
Anyway I cannot stretch enough how thankful I am for you taking the time to help me out. Many many thanks and I actually learned a lot. :)
First thing: get XDebug running ;D

@github-actions
Copy link

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 19, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants