データベース破損により多数のユーザーが破損

I have a real issue with many of my users. The users can be seen in admin panel like this:

But when I try to reveal their email address, It wont show anything to me. And also their public profile gives a 404 error.

As far as I see, all of these users are almost inactive (they are active in terms of activation but inactive in terms of activity in forum). So I think maybe its been caused by a broken automatic inactive user removal in the very long past.

「いいね!」 1

Another thing I notice:

If I inactivate, and then activate them, they get fixed!

「いいね!」 2

If a user is inactive for a certain length of time (730 days by default) they are automatically inactivated. The setting is in your dashboard under Settings/Users and scroll almost down to the bottom. That is where you’ll see that. But, it’s not necessary to make any changes for the sake of making a change. If those users haven’t logged in for 2 years, it makes no sense to reactivate them unless they start showing up again. :wink:

「いいね!」 4

No. My problem is not this. The dashboard says the users are activated.

Seems similar to the issue I’m having. Could you check if the affected names have duplicates or ‘very near matches’ in your database? For example user.user and useruser.

「いいね!」 1

Yes affected users are among those usernames that are very popular. so discourse suggest a near match username. I signup users with api. so I get a username from user. then I check it against discourse api and if its already taken, I would automatically use whatever discourse suggest.

「いいね!」 1

btw with help of @RGJ we nailed the problem down to this two condisions:

「いいね!」 3

To add to that, the issue @hosna is having is clearly an issue on the database level. It seems like there is some corruption in the users table. Copying the contents to a new table solves these issues.

That said, I did see two occurrences of @bartv’s issue in @hosna’s database (those were the two duplicates before Sept 22 and they both had a dot in their username) but I am not sure if these two issues are related. They just have the same symptoms.

「いいね!」 4

Sounds like a corrupt database index. REINDEX TABLE users should solve the problem.

「いいね!」 2

What about the duplicate usernames? I have many same usernames being used for 2 distinct users.

The issue is acknowledged here:

「いいね!」 1

That’s probably a side effect of a corrupt index. You might need to clean that up manually before the reindexing works.

「いいね!」 2

Can you explain how a corrupt index might happen? to prevent it in the future?

Hardware failure, bug in Postgres,… hard to tell. It happens.

Except that that is impossible since the index is broken.
This does the trick:

# create a temporary table without constraints and copy the contents into it
create table users_test (like users);
insert into users_test select * from users;

# remove duplicate usernames case sensitive, the dupes are after Sept 22
delete from users_test where username in (
  select username 
  from users_test 
  group by username 
  having count(username)>1
) and created_at>'2019-09-22' ;

# remove duplicate usernames case insensitive, the dupes are after Sept 22
delete from users_test where lower(username) in (
  select lower(username) 
  from users_test 
  group by lower(username) 
  having count(lower(username))>1
) and created_at > '2019-09-22' ;

# two more problems left, delete them individually
delete from users_test where id in (184534,130826);

# create a new table with constraints and copy the users
create table users_clean (like users including indexes);
insert into users_clean select * from users_test;

and then rename users to users_old and users_clean to users.

「いいね!」 3

ここで一言付け加えさせてください。これは、壊れたユーザーデータ以上にデータベースを破損させる可能性があります

テーブルをリネームしたため、多くの制約がまだ users_old に依存しており、私たちはアップグレードの途中で立ち往生してしまいました。この不完全な修正を適用してから数日後にのみこの問題が表面化しました。また、like users including indexes だけでは不十分です(例えば、id シーケンスが無視されてしまいます)。

おっしゃる通りです。テーブル名を変更した後、制約を再作成する必要があったことを確かに覚えております。
この重要な見落としについてお詫び申し上げます。

私のメモによると:

alter table poll_votes drop constraint fk_rails_b64de9b025;
alter table poll_votes add constraint fk_rails_b64de9b025 FOREIGN KEY (user_id) REFERENCES users(id);

alter table user_security_keys drop constraint fk_rails_90999b0454;
alter table user_security_keys add  constraint fk_rails_90999b0454 FOREIGN KEY (user_id) REFERENCES users(id);

そして現在では、以下も必要です:

alter table bookmarks drop constraint fk_rails_c1ff6fa4ac;
alter table bookmarks add  constraint fk_rails_c1ff6fa4ac FOREIGN KEY (user_id) REFERENCES users(id);

重要な免責事項として:これを適用するのは、自分が何をしているかを完全に理解している場合に限ってください

「いいね!」 1

これは、users_old に影響を与える制約を pg_catalog で照会した後に私たちが発見した内容と確かに一致しているようです。

また、登録機能を壊さないためには、少なくとも including defaults を含める必要があったと記憶しています。

修正ありがとうございます!

「いいね!」 1