Skip to content Skip to sidebar

This is the technical support forum for WPML - the multilingual WordPress plugin.

Everyone can read, but only WPML clients can post here. WPML team is replying on the forum 6 days per week, 22 hours per day.

Sun Mon Tue Wed Thu Fri Sat
- 8:00 – 14:00 8:00 – 14:00 8:00 – 14:00 8:00 – 14:00 8:00 – 14:00 -
- 15:00 – 17:00 15:00 – 17:00 15:00 – 17:00 15:00 – 17:00 15:00 – 17:00 -

Supporter timezone: Europe/Madrid (GMT+02:00)

Tagged: 

This topic contains 26 replies, has 3 voices.

Last updated by Nigel 9 months, 1 week ago.

Assisted by: Nigel.

Author Posts
April 14, 2023 at 12:21 pm #13473671

hugoC-18

Other related issues :
- https://wpml.org/forums/topic/sql-database-stop-working-after-enable-wpml-plugin/
- https://wpml.org/forums/topic/binlog-in-mysql-shows-wpml-notices/

- MySQL 8
- WordPress 6.2
- WPML 4.6.3

We're having trouble with the MySQL binlog. WPML is saving its notices option (`wpml_notices` in the `wp_options` table) on almost every request, even on the public site. Closing the notices does not affect it, and completely removing all `admin_notices` also doesn't stop WPML from saving the `wpml_notices`.

This problem seems to always have been there for a few years. We checked older WordPress websites that we've made and they have the same issue, but it's only been noticed recently because our most recent website has a lot of traffic, both in public and admin sections. The binlog for this website's MySQL has become huge very quickly.

After hours of diagnosis on our side, we found that it was WPML saving data at every request that was the main culprit. Displaying the website's homepage shouldn't be saving anything in the database, especially not notices for admin users.

What we found, to help you debug on your side :
`WPML_Notices#add_notice` in `sitepress-multilingual-cms/classes/notices/class-wpml-notices.php` seems to be where the problem is. The serialized notices array is always different for each request, so it always gets saved.

When reloading a page without cache, the value of `restricted_to_user_ids` in `wpml_notices` seems to switch between two values. It also occurs when not connected and on the public side of the website.
It doesn't depend on dev or prod environment, or on other plugins, since it happens on all of our websites using WPML.

First data save :

O:11:"WPML_Notice":24:{s:30:"WPML_Noticedisplay_callbacks";a:0:{}s:15:"WPML_Noticeid";s:35:"WPML_User_Languagehow_to_set_notice";s:17:"WPML_Noticetext";s:412:"   <h2>Voulez-vous que l'administrateur WordPress soit dans une autre langue ?</h2>
    <p>
      WPML permet à chaque utilisateur de choisir la langue d'administration, sans rapport avec la langue dans laquelle les visiteurs verront le front-end du site.     <br/>
      <br/>
      Accédez à votre <a href="<em><u>hidden link</u></em>">profil</a> pour choisir votre langue d'administration.   </p>
    ";s:27:"WPML_Noticecollapsed_text";N;s:18:"WPML_Noticegroup";s:18:"WPML_User_Language";s:35:"WPML_Noticerestricted_to_user_ids";a:1:{i:0;i:0;}s:20:"WPML_Noticeactions";a:0:{}s:28:"WPML_Noticecss_class_types";a:1:{i:0;s:4:"info";}s:24:"WPML_Noticecss_classes";a:0:{}s:24:"WPML_Noticedismissible";b:1;s:31:"WPML_Noticeexclude_from_pages";a:0:{}s:21:"WPML_Noticehideable";b:0;s:24:"WPML_Noticecollapsable";b:0;s:30:"WPML_Noticerestrict_to_pages";a:0:{}s:38:"WPML_Noticerestrict_to_page_prefixes";a:0:{}s:35:"WPML_Noticerestrict_to_screen_ids";a:0:{}s:34:"WPML_Noticehide_if_notice_exists";N;s:43:"WPML_Noticedismissible_for_different_text";b:1;s:31:"WPML_Noticedefault_group_name";s:7:"default";s:25:"WPML_Noticecapabilities";a:1:{i:0;s:14:"manage_options";}s:26:"WPML_Noticedismiss_reset";b:0;s:18:"WPML_Noticeflash";b:0;s:25:"WPML_Noticenonce_action";N;s:22:"WPML_Noticetext_only";b:0;}

Next data save, after reloading :

O:11:"WPML_Notice":24:{s:30:"WPML_Noticedisplay_callbacks";a:0:{}s:15:"WPML_Noticeid";s:35:"WPML_User_Languagehow_to_set_notice";s:17:"WPML_Noticetext";s:412:"   <h2>Voulez-vous que l'administrateur WordPress soit dans une autre langue ?</h2>
    <p>
      WPML permet à chaque utilisateur de choisir la langue d'administration, sans rapport avec la langue dans laquelle les visiteurs verront le front-end du site.     <br/>
      <br/>
      Accédez à votre <a href="<em><u>hidden link</u></em>">profil</a> pour choisir votre langue d'administration.   </p>
    ";s:27:"WPML_Noticecollapsed_text";N;s:18:"WPML_Noticegroup";s:18:"WPML_User_Language";s:35:"WPML_Noticerestricted_to_user_ids";a:1:{i:1;i:1;}s:20:"WPML_Noticeactions";a:0:{}s:28:"WPML_Noticecss_class_types";a:1:{i:0;s:4:"info";}s:24:"WPML_Noticecss_classes";a:0:{}s:24:"WPML_Noticedismissible";b:1;s:31:"WPML_Noticeexclude_from_pages";a:0:{}s:21:"WPML_Noticehideable";b:0;s:24:"WPML_Noticecollapsable";b:0;s:30:"WPML_Noticerestrict_to_pages";a:0:{}s:38:"WPML_Noticerestrict_to_page_prefixes";a:0:{}s:35:"WPML_Noticerestrict_to_screen_ids";a:0:{}s:34:"WPML_Noticehide_if_notice_exists";N;s:43:"WPML_Noticedismissible_for_different_text";b:1;s:31:"WPML_Noticedefault_group_name";s:7:"default";s:25:"WPML_Noticecapabilities";a:1:{i:0;s:14:"manage_options";}s:26:"WPML_Noticedismiss_reset";b:0;s:18:"WPML_Noticeflash";b:0;s:25:"WPML_Noticenonce_action";N;s:22:"WPML_Noticetext_only";b:0;}
April 17, 2023 at 10:40 am #13486989

Nigel
WPML Supporter since 02/2016

Timezone: Europe/Madrid (GMT+02:00)

Hi there

I'm having trouble reproducing this.

On my own WPML install, that add_notice method is never called. (And reviewing the code it's hard to track how it is, because it is added as a callback to the 'otgs_add_notice' action, and there is no corresponding do_action call for that hook that would trigger the callback.)

I've set a breakpoint at that method so that I could inspect the call stack to see if it is being called directly, but as it never gets called there is nothing for me to check.

What led you to that method as the source of the problem?

April 17, 2023 at 1:26 pm #13488181

hugoC-18

Which methods get called in WPML's code is not the important part. The fact that it saves the entire `wpml_notices` serialized array at every request is the problem. And also the part where it saves that data when a non-connected user navigates the public website.

I don't know if you have access to it, but I provided the WPML debug info when I posted the issue. That seemed to contain the necessary information to set up WPML in a similar way to help debug it.

That `add_notice` function seems to be called directly from a bunch of other places (other than that action that has no do_action).
When you look into the included code sections in my original message, the `wpml_notices` array contains many different notices from separate sections of WPML: user language preferences, taxonomy translations, etc. `add_notice` is called directly from other files in WPML.

I made a stack trace for the save_notice function and reloaded my homepage (keep in mind that this is only one of the many notices that can get saved):

Called WPML_Notices#save_notices in file /var/www/html/wp-content/plugins/sitepress-multilingual-cms/classes/notices/class-wpml-notices.php at line 139
Called WPML_Notices#add_notice in file /var/www/html/wp-content/plugins/sitepress-multilingual-cms/classes/user-language/class-wpml-user-language.php at line 290
Called WPML_User_Language#add_how_to_set_notice in file /var/www/html/wp-content/plugins/sitepress-multilingual-cms/vendor/wpml/fp/core/Either.php at line 207
Called WPML\FP\Right#map in file /var/www/html/wp-content/plugins/sitepress-multilingual-cms/vendor/wpml/fp/core/Either.php at line 257
Called WPML\FP\Right#chain in file /var/www/html/wp-content/plugins/sitepress-multilingual-cms/vendor/wpml/fp/core/Promise.php at line 24
Called WPML\FP\Promise#resolve in file /var/www/html/wp-content/plugins/sitepress-multilingual-cms/vendor/wpml/wp/classes/Hooks.php at line 50
Called WPML\LIB\WP\Hooks#WPML\LIB\WP\{closure} in file /var/www/html/wp-includes/class-wp-hook.php at line 308
Called WP_Hook#apply_filters in file /var/www/html/wp-includes/class-wp-hook.php at line 332
Called WP_Hook#do_action in file /var/www/html/wp-includes/plugin.php at line 517
Called #do_action in file /var/www/html/wp-settings.php at line 623
Called #require_once in file /var/www/html/wp-config.php at line 138
Called #require_once in file /var/www/html/wp-load.php at line 50
Called #require_once in file /var/www/html/wp-blog-header.php at line 13
Called #require in file /var/www/html/index.php at line 17
April 17, 2023 at 2:30 pm #13488603

Nigel
WPML Supporter since 02/2016

Timezone: Europe/Madrid (GMT+02:00)

Thanks for that.

It shows that the process is initiated via the core init hook, but unfortunately it is not available from that call stack what action added to the init hook was responsible, so it doesn't narrow it down very much.

I'm raising this with my second tier colleagues for advice on how to proceed, and I'll get back to you when I've heard from them.

I suspect they will confirm we need a copy of the site to be able to step through the code execution to be able to identify the cause, so let me pre-empt that by asking if that would be okay.

If you were able to provide a package of your site made with Duplicator that would be helpful.

(If so you can go ahead and share a link to the files on Dropbox or similar, such links are automatically hidden and other users won't be able to see it.)

April 18, 2023 at 12:17 pm #13495491

Nigel
WPML Supporter since 02/2016

Timezone: Europe/Madrid (GMT+02:00)

My colleague's first suggestion is to delete the following rows from the wp_options table:

wpml_notices
_wpml_dismissed_notices
_wpml_user_dismissed_notices
icl_admin_messages

To the extent that they are needed, they will be regenerated.

Could you please try that and see if it helps?

April 24, 2023 at 6:10 pm #13529359

Maarten

I can confirm this issue, same thing is happening for me. I removed the suggested rows in the wp_options table but it's still happening. Warnings are added in my log every second.

Warning: trying to save option 'wpml_notices' with the size of 79400 bytes

Any solution to this?

April 25, 2023 at 7:10 am #13530983

Nigel
WPML Supporter since 02/2016

Timezone: Europe/Madrid (GMT+02:00)

@Maarten no updates so far.

Could you please open a new thread and link it to this one so that we can interact with you directly. I think we are going to need a copy of a site that has this issue to be able to identify the cause, so if you are in a position to provide that, it will help greatly.

April 25, 2023 at 11:52 am #13532925

hugoC-18

Removing the rows did not fix the problem. Do you need the copy of our site ?
Do I just post the link here in the text and it will be hidden from the public ?

April 25, 2023 at 1:20 pm #13533421

Nigel
WPML Supporter since 02/2016

Timezone: Europe/Madrid (GMT+02:00)

Please provide a copy, as described here: https://wpml.org/faq/provide-supporters-copy-site/

It will help keep the file size down if you exclude the uploads folder, we shouldn't need the site media to test this.

You can paste a link to dropbox or similar and it will automatically be hidden.

Thanks.

April 27, 2023 at 12:28 pm #13549629

hugoC-18

hidden link

Here is the complete website. The database is in the db folder, and the instructions to start the website are in the README. I tried to make this as simple as possible to setup.

April 28, 2023 at 9:27 am #13556059

Nigel
WPML Supporter since 02/2016

Timezone: Europe/Madrid (GMT+02:00)

Thanks for that.

I managed to get a copy of your site up and running (I don't use Docker) and run some tests on it.

I could see the calls to update the options table for the wpml_notices option, even just when loading the home page on the front end.

I located where in our code this happens (its in a callback to the shutdown action) and used Xdebug to step through the code execution to identify why the option gets updated.

The option itself looked malformed, and I deleted the wpml_notices option directly from the database.

That prompts the option to get recreated, but then on subsequent page loads the problem no longer occurs.

Could you please try again on your server deleting the wpml_notices option from the options table, load the page, and then load it again to see whether the option keeps getting resaved.

For reference, let me share where in the code this is triggered, so that you can check the same yourself if you wish.

In the file sitepress-multilingual-cms/classes/notices/class-wpml-notices.php, line 177, there is this method:

	public function save_to_option() {
		if ( $this->original_notices_md5 !== md5( maybe_serialize( $this->notices ) ) ) {
			update_option( self::NOTICES_OPTION_KEY, $this->notices, false );
		}
	}

The left and right of that condition do not match, and hence the option gets updated. (Except, it doesn't after deleting the existing option entry and letting WPML re-build it.)

May 4, 2023 at 7:28 pm #13589841

hugoC-18

We have deleted the wpml_notices row in wp_options on our production website and the issue is not resolved.

WPML is still saving the wpml_notices value in the database on almost every request. It seems to be more apparent when multiple people are accessing the website.

May 5, 2023 at 7:25 am #13591231

Nigel
WPML Supporter since 02/2016

Timezone: Europe/Madrid (GMT+02:00)

It only happens on the production server?

Is there a staging server where the issue also occurs that we could work on?

Working on the production server would be a last resort.

Let me set a private reply to get credentials for a staging site, if you have one available.

May 5, 2023 at 9:46 am #13592753

Maarten

I did a bit more testing, and the issue is indeed related to having multiple logged in users browsing the site or backend. WPML saves the notices for each user in the option table, but since it's using the same field for each user, the saved option and the option is trying to save keeps being different. Since there are multiple users with different notices... I hope I'm explaining this somewhat clear.

WPML also saves the notices whenever an ajax call is made to admin-ajax.php, which can be quite often if you have multiple logged in users.

If you want to test it, you need to log in with multiple users (in different browsers, or container tabs) and browse around. If you change the code to this, you can see what happens in the logs.

	public function save_to_option() {
		error_log($this->original_notices_md5);
		error_log(md5( maybe_serialize( $this->notices ) ));
		error_log($this->original_notices_md5 !== md5( maybe_serialize( $this->notices ) ));
		if ( $this->original_notices_md5 !== md5( maybe_serialize( $this->notices ) ) ) {
			update_option( self::NOTICES_OPTION_KEY, $this->notices, false );
		}
	}

I hope that helps with testing...

May 8, 2023 at 7:01 am #13602165

Nigel
WPML Supporter since 02/2016

Timezone: Europe/Madrid (GMT+02:00)

Thanks for that @Maarten

My colleague looked into this further and proposes a workaround for the problem, and has escalated the issue to the developers.

(If you make the below changes, keep an eye on the release notes for the next release of WPML to check if a fix is included; if it doesn't make it into the next release, you will need to re-apply these changes.)

You need to edit the file sitepress-multilingual-cms/classes/notices/class-wpml-notices.php and update the function get_all_notices (from line 55) like so:

	public function get_all_notices() {
		$all_notices = get_option( self::NOTICES_OPTION_KEY . get_current_user_id() );
		if ( ! is_array( $all_notices ) ) {
			$all_notices = array();
		}
		return $all_notices;
	}

Also, update the function save_to_option (from line 177) like so:

	public function save_to_option() {
		if ( $this->original_notices_md5 !== md5( maybe_serialize( $this->notices ) ) ) {
			update_option( self::NOTICES_OPTION_KEY . get_current_user_id(), $this->notices, false );
		}
	}

If you run into problems using that let me know, otherwise I think we should be able to close here @hugoC-18

Thanks for your patience.