많은 사용자들에서 실제 문제가 발생하고 있습니다. 관리자 패널에서 사용자는 다음과 같이 표시됩니다:
하지만 이메일 주소를 표시하려고 하면 아무것도 나타나지 않습니다. 또한 공개 프로필에 접근하면 404 오류가 발생합니다.
제 판단으로는 이 사용자들은 대부분 비활성 상태입니다(계정 활성화 상태는 유지되고 있지만, 포럼 활동 측면에서는 비활성입니다). 따라서 아주 오래전에 자동 비활성 사용자 제거 기능이 고장 났기 때문이라고 생각합니다.
많은 사용자들에서 실제 문제가 발생하고 있습니다. 관리자 패널에서 사용자는 다음과 같이 표시됩니다:
하지만 이메일 주소를 표시하려고 하면 아무것도 나타나지 않습니다. 또한 공개 프로필에 접근하면 404 오류가 발생합니다.
제 판단으로는 이 사용자들은 대부분 비활성 상태입니다(계정 활성화 상태는 유지되고 있지만, 포럼 활동 측면에서는 비활성입니다). 따라서 아주 오래전에 자동 비활성 사용자 제거 기능이 고장 났기 때문이라고 생각합니다.
또 하나 눈치챈 점:
비활성화했다가 다시 활성화하면 문제가 해결됩니다!
특정 기간 동안 비활성 상태인 사용자(기본값 730일)는 자동으로 비활성화됩니다. 이 설정은 대시보드의 설정/사용자 항목에서 찾을 수 있으며, 거의 맨 아래로 스크롤하면 해당 옵션이 보입니다. 하지만 변경을 위해 변경할 필요는 없습니다. 해당 사용자가 2년 동안 로그인하지 않았다면, 다시 활동하기 시작하기 전까지는 재활성화하는 것이 의미가 없습니다. ![]()
아니요. 제 문제는 그쪽이 아닙니다. 대시보드에는 사용자들이 활성화되어 있다고 표시되어 있습니다.
제가 겪고 있는 문제와 비슷해 보입니다. 데이터베이스에서 해당 이름들이 중복되거나 ‘매우 유사한’ 이름이 있는지 확인해 주시겠어요? 예를 들어 user.user와 useruser처럼요.
네, 영향받는 사용자들은 매우 인기 있는 사용자 이름 중 일부입니다. 그래서 Discourse는 유사한 사용자 이름을 제안합니다. 저는 API를 통해 사용자를 가입시키는데, 사용자에게 사용자 이름을 받은 후 Discourse API와 대조하여 이미 사용 중인지 확인합니다. 이미 사용 중이라면 Discourse가 제안하는 이름을 자동으로 사용하게 됩니다.
참고로 @RGJ의 도움으로 문제를 다음 두 조건으로 좁혀 보았습니다:
손상된 데이터베이스 인덱스인 것 같습니다. REINDEX TABLE users를 실행하면 문제가 해결될 것입니다.
중복된 사용자 이름은 어떻게 처리해야 하나요? 서로 다른 두 사용자가 동일한 사용자 이름을 사용하고 있는 경우가 많습니다.
해당 문제는 여기서 확인되었습니다:
그것은 손상된 인덱스의 부작용일 가능성이 높습니다. 재인덱싱이 정상적으로 작동하려면 먼저 해당 인덱스를 수동으로 정리해야 할 수 있습니다.
손상된 인덱스가 어떻게 발생할 수 있는지, 그리고 이를 앞으로 방지하려면 어떻게 해야 하는지 설명해 주시겠어요?
하드웨어 장애, Postgres의 버그… 정확히 알기 어렵습니다. 이런 일은 자주 발생합니다.
하지만 인덱스가 깨져 있으므로 그렇게 하는 것은 불가능합니다.
다음은 문제를 해결하는 방법입니다:
# 제약 조건이 없는 임시 테이블을 만들고 내용을 복사합니다
create table users_test (like users);
insert into users_test select * from users;
# 대소문자를 구분하여 중복된 사용자 이름을 제거합니다. 중복 항목은 9월 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' ;
# 대소문자를 구분하지 않고 중복된 사용자 이름을 제거합니다. 중복 항목은 9월 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' ;
# 남은 두 가지 문제를 개별적으로 삭제합니다
delete from users_test where id in (184534,130826);
# 제약 조건이 있는 새 테이블을 만들고 사용자를 복사합니다
create table users_clean (like users including indexes);
insert into users_clean select * from users_test;
그 다음 users를 users_old로, users_clean를 users로 이름 변경합니다.
여기서 한마디 하고 싶습니다. 이것이 깨진 사용자들보다 데이터베이스를 더 심각하게 손상시킬 수 있습니다!
우리는 현재 업그레이드의 중간에 멈춰 있습니다. 테이블 이름을 변경했기 때문에 많은 제약 조건이 여전히 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);
또한 중요한 주의사항으로: 무엇을 하는지 확실히 아는 경우에만 이 방법을 사용하세요!
users_old에 영향을 미치는 제약 조건을 pg_catalog에서 조회한 결과와 일치하는 것 같습니다.
또한, 등록 기능이 깨지지 않도록 하려면 including defaults가 최소한으로 필요합니다.
수정해 주셔서 감사합니다!