Tantos usuarios dañados por base de datos corrupta

Tengo un problema real con muchos de mis usuarios. Los usuarios se pueden ver en el panel de administración de la siguiente manera:

Pero cuando intento revelar su dirección de correo electrónico, no se muestra nada. Además, su perfil público devuelve un error 404.

Por lo que he podido observar, todos estos usuarios están casi inactivos (están activos en términos de activación de cuenta, pero inactivos en cuanto a actividad en el foro). Creo que esto podría haber sido causado por una eliminación automática de usuarios inactivos que falló hace mucho tiempo.

Otra cosa que noto:

Si los desactivo y luego los activo, ¡se arreglan!

Si un usuario está inactivo durante un cierto período de tiempo (730 días por defecto), se desactiva automáticamente. La configuración se encuentra en tu panel de control bajo Configuración/Usuarios; simplemente baja casi hasta el final y ahí lo verás. Sin embargo, no es necesario hacer cambios solo por cambiar. Si esos usuarios no han iniciado sesión en 2 años, no tiene sentido reactivarlos a menos que vuelvan a aparecer. :wink:

No. Mi problema no es ese. El panel indica que los usuarios están activados.

Parece similar a el problema que tengo. ¿Podrías verificar si los nombres afectados tienen duplicados o ‘coincidencias muy cercanas’ en tu base de datos? Por ejemplo user.user y useruser.

Sí, los usuarios afectados son aquellos con nombres de usuario muy populares, por lo que Discourse sugiere un nombre de usuario similar. Me inscribo a los usuarios mediante la API. Obtengo un nombre de usuario del usuario, luego lo verifico contra la API de Discourse y, si ya está tomado, uso automáticamente lo que sugiere Discourse.

Por cierto, con la ayuda de @RGJ, hemos identificado el problema en estas dos condiciones:

Para añadir a eso, el problema que tiene @hosna es claramente un problema a nivel de base de datos. Parece que hay cierta corrupción en la tabla de usuarios. Copiar el contenido a una nueva tabla resuelve estos problemas.

Dicho esto, sí vi dos ocurrencias del problema de @bartv en la base de datos de @hosna (esos fueron los dos duplicados antes del 22 de septiembre y ambos tenían un punto en su nombre de usuario), pero no estoy seguro de si estos dos problemas están relacionados. Simplemente tienen los mismos síntomas.

Suena como un índice de base de datos corrupto. REINDEX TABLE users debería resolver el problema.

¿Qué pasa con los nombres de usuario duplicados? Tengo muchos nombres de usuario idénticos utilizados por dos usuarios distintos.

El problema está reconocido aquí:

Eso probablemente sea un efecto secundario de un índice corrupto. Es posible que necesites limpiarlo manualmente antes de que la reindexación funcione.

¿Puedes explicar cómo podría ocurrir un índice corrupto? ¿Cómo prevenirlo en el futuro?

Fallo de hardware, error en Postgres… es difícil saberlo. Sucede.

Excepto que eso es imposible ya que el índice está roto.
Esto hace el trabajo:

# crear una tabla temporal sin restricciones y copiar el contenido en ella
create table users_test (like users);
insert into users_test select * from users;

# eliminar nombres de usuario duplicados con sensibilidad a mayúsculas, los duplicados son después del 22 de septiembre
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' ;

# eliminar nombres de usuario duplicados sin sensibilidad a mayúsculas, los duplicados son después del 22 de septiembre
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' ;

# quedan dos problemas más, elimínalos individualmente
delete from users_test where id in (184534,130826);

# crear una nueva tabla con restricciones y copiar los usuarios
create table users_clean (like users including indexes);
insert into users_clean select * from users_test;

y luego renombra users a users_old y users_clean a users.

Quiero intervenir aquí para decir que esto podría dañar tu base de datos aún más que los usuarios rotos.

Ahora estamos atrapados a mitad de camino entre actualizaciones, ya que muchas restricciones aún dependen de users_old desde que renombramos la tabla. Esto solo se mostró como un problema unos días después de aplicar esta solución aparentemente incompleta. Además, like users including indexes no es suficiente (por ejemplo, ignorará la secuencia id).

Tienes toda la razón, efectivamente recuerdo haber tenido que recrear las restricciones después de renombrar las tablas.
Mis disculpas por esta importante omisión.

De mis notas:

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);

Y actualmente también:

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

Y como descargo de responsabilidad importante: ¡solo usa esto cuando sepas absolutamente lo que estás haciendo!

Esto parece coincidir con lo que encontramos al consultar pg_catalog para las restricciones que afectan a users_old.

Además, recuerdo que including defaults era como mínimo necesario para no romper el registro.

¡Gracias por la corrección!