1

what determines what user id to which a new user account will be assigned? On my site, Drupal 7.37, new user accounts are assigned to non-sequential user ids. All new users now have user ids well above 3500.

  • 4
    You already asked this question 3 days ago. Instead of asking it again, read the feedback and update the previous question: drupal.stackexchange.com/q/223701/9921 – Neograph734 Dec 26 '16 at 22:21
  • 1
    The titles are very similar @Neograph734 but the ultimate questions are different (what determines what user id to which a new user account will be assigned? and how can I ensure that new user ids do not exceed the value that causes the user account to get blocked?). The original one is (probably fairly) closed as too broad as there are dozens of combinations of things that could make that happen...this one does have a definitive answer – Clive Dec 27 '16 at 1:00
  • @clive fair enough :) – Neograph734 Dec 27 '16 at 10:28
2

There are a couple of layers here...

Any code that calls user_save can technically affect what ID is assigned. If the account object has a uid property, that is used, otherwise it comes from the database:

// Allow 'uid' to be set by the caller. There is no danger of writing an
// existing user as drupal_write_record will do an INSERT.
if (empty($account->uid)) {
  $account->uid = db_next_id(db_query('SELECT MAX(uid) FROM {users}')->fetchField());
}

So if an ID is provided, great, if not (which is the norm), it gets more complicated.

The users table doesn't have an auto-increment column (probably because an ID of 0 is used for the anonymous user, and there's no way to support that across all DB platforms). If you were to just get the last inserted user ID + 1, you're open to race conditions when other requests get the same ID returned before the first script has had a chance to insert the record into users.

Because of that, the Sequence API is used. The sequences table has a single, auto-incremented primary key column. When a new, unique, identifier is required, a record is inserted into that table, and the auto-assigned ID is returned to Drupal. That ensures it's not susceptible to race conditions, as the operation has already completed and any other requests would be guaranteed a new ID.

If you just need to hack around the problem you mentioned, and you're not worried about or prepared to take the risk of race conditions, add this to a custom module:

function MYMODULE_user_presave(&$edit, $account, $category) {
  if (!empty($account->is_new)) {
    $account->uid = db_query('SELECT MAX(uid) FROM {users}')->fetchField() + 1;
  }
}
  • this seems pretty convoluted - especially when I follow the code and documentation and there is something about the 'sequence' table. I am not at clear what the LOGIC is that determines how the "next" user id should be chosen. Why is not simply one more than the highest existing user id?? – dascher Dec 26 '16 at 23:46
  • It's convoluted because it's solving quite a complex problem - sequences contains surrogate primary keys for tables, like users, that don't have an auto-increment column. (Drupal uses an ID of 0 for the anonymous user, which isn't a valid identifier in some/all engines and you'd be encouraging race conditions by simply selecting the highest ID + 1). By inserting a new record into that table every time, and returning its primary key, you're guaranteed an identifier that will be unique throughout the system, as long as all interaction with the table(s) in question uses the same method – Clive Dec 26 '16 at 23:59
  • That's why you get jumps in the user ids btw, something else is using the sequence table too. I'll consolidate that into a better answer, two ticks – Clive Dec 27 '16 at 0:02
  • I had been hoping to get control of the value for the next user id as a temporary workaround to the real problem I am having where accounts with user ids higher than some value (I have not yet pinned down the boundary value) are getting blocked by something I have not yet identified... presumably by some module, but it seems odd for some random module to decide to block a user account based on its id exceeding some value. It sounds like I will not be able to get control of the user ids and therefor, will not be able to use that as a temporary workaround. – dascher Dec 27 '16 at 0:49
  • Getting control of it's easy enough, I updated the answer with an example – Clive Dec 27 '16 at 1:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.