Problem/Motivation

The sequences API was introduced in #356074: Provide a sequences API to solve the problem of some tables not having serial fields (and serial field implementations being broken on some databases at that time).

The MySQL implementation implements two functions nextId() and nextIdDelete().

The nextId() function inserts a value into the sequences table and reads the last insert ID and then sets $this->cleanup = TRUE.

On __destruct() of the function all values except the last one inserted are deleted using:

      $max_id = $this->query('SELECT MAX(value) FROM {sequences}')->fetchField();
      // We know we are using MySQL here, no need for the slower db_delete().
      $this->query('DELETE FROM {sequences} WHERE value < :value', array(':value' => $max_id));

And this creates problems for scalability:

When many clients simultaneously need to insert new users (which uses db_next_id()), then many MySQL processes get occupied that simultaneously are deleting from the sequences table, which creates a stampede that kills the throughput completely.

In Drupal 6 the uid was a serial field instead.

In Drupal 8 it seems like db_next_id() is no longer used for user accounts, but this should be clarified

Proposed resolution

Run the cleanup during the cron job.

That is a little messy, because the sequences table depends on the used database type ('mysql', 'sqlite', ...), but it should be doable as the sequences schema is already installed by system module.

In addition or as an alternative to that we could check the size of the table (row count usually is pretty quick) during __destruct() and if it exceeds a certain limit then:

lock() => delete() => unlock() though that could get messy during __destruct().

Another possibility would be to add a random() jitter to the threshold to decrease the probability of two processes wanting to cleanup the table at the same time().

e.g. limit = 100000, jitter = 1000 would mean that probably there is a random() distribution of the requests and just 1 or 2 trigger the cleanup at the same time, which has the advantage of not needing a lock.

And 100000 BIGINTs would need around 780 kB of storage space, so should be neglectable.

(In detail: db_select("SELECT COUNT(*) FROM {sequences}")->result() - rand(0, jitter) > limit )

Remaining tasks

- Discuss
- Implement

User interface changes

- None

API changes

- Only internal changes

Data model changes

- None

Comments

Fabianx created an issue. See original summary.

Fabianx’s picture

Title: Sequences API (mysql) kills MySQL server due to cleanup phase » Sequences API (mysql) kills MySQL server performance due to cleanup phase
Fabianx’s picture

Version: 7.x-dev » 8.4.x-dev
Priority: Critical » Major

The same problem is in Drupal 8 (found the code in core/modules/user/src/UserStorage.php) so moving there, but degrading to major as it can be circumvented there.

Hm, it can be circumvented in Drupal 7 as well by setting a uid explicitly in pre_save().

It remains a tricky issue.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

larowlan’s picture