Move a Discourse site to another VPS with rsync

불행히도 백업을 불러오려 해도 성공하지 못합니다. 데이터베이스가 어떤 방식으로든 분기(diverge)된 것 같습니다. 컨테이너가 실행되지 않을 때 파일을 추출하는 것은 꽤 번거롭지만, /etc/passwd 파일을 컨테이너에서 추출해 보겠습니다.

복구가 안 되는 건가요, 아니면 서버로 백업을 올려서 복구하는 것 자체가 불가능한 건가요?

복원되지 않아요. 새 설치 환경에서 다시 시도해 볼 수는 있지만, 임포터가 멈추기 전에 확인했던 로그에는 필드 불일치에 대한 내용이 있었어요. 오래된… 2.9.x 인스턴스인 것 같나요? 메모를 손에 바로 두지 못해서 정확히 기억나지 않아요.

기록을 위해 말씀드리면, 우리 팀의 한 전문가가 PostgreSQL이 실행되도록 컨테이너에 필요한 적절한 권한을 rsync로 동기화하는 방법을 알아냈습니다:

rsync -rog --delete --perms --numeric-ids root@x.x.x.x:/var/discourse/ /var/discourse
4개의 좋아요

rsync 관련 문제를 겪고 있는데, 처음에는 모두 정상적으로 진행되는 것처럼 보였습니다. 그런데 nit가 재빌드되지 않나요? 일부는 포트 문제와 관련이 있을 수도 있는 것 같습니다?

I, [2025-01-05T06:32:16.218961 #1]  INFO -- : > exec chpst -u redis -U redis /usr/bin/redis-server /etc/redis/redis.conf
I, [2025-01-05T06:32:16.224597 #1]  INFO -- : > sleep 10
2175:C 05 Jan 2025 06:32:16.236 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
2175:C 05 Jan 2025 06:32:16.236 # Redis version=7.0.7, bits=64, commit=00000000, modified=0, pid=2175, just started
2175:C 05 Jan 2025 06:32:16.236 # Configuration loaded
2175:M 05 Jan 2025 06:32:16.238 * monotonic clock: POSIX clock_gettime
2175:M 05 Jan 2025 06:32:16.238 # Warning: Could not create server TCP listening socket *:6379: bind: Address already in use
2175:M 05 Jan 2025 06:32:16.238 # Failed listening on port 6379 (TCP), aborting.
I, [2025-01-05T06:32:26.228550 #1]  INFO -- :
I, [2025-01-05T06:32:26.228998 #1]  INFO -- : > cd /var/www/discourse && su discourse -c 'bundle exec rake db:migrate'
URGENT: Failed to initialize site default: ActiveRecord::ConnectionNotEstablished connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: No such file or directory
        Is the server running locally and accepting connections on that socket?

/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:69:in `rescue in new_client'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:57:in `new_client'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:982:in `connect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:994:in `reconnect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:662:in `block in reconnect!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/concurrency/null_lock.rb:9:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:661:in `reconnect!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:763:in `block in verify!'/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/concurrency/null_lock.rb:9:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:754:in `verify!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:771:in `connect!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:977:in `block in with_raw_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/concurrency/null_lock.rb:9:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:976:in `with_raw_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql/quoting.rb:128:in `quote_string'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract/quoting.rb:76:in `quote'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql/quoting.rb:122:in `quote'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql/schema_statements.rb:1099:in `quoted_scope'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql/schema_statements.rb:1076:in `data_source_sql'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract/schema_statements.rb:60:in `table_exists?'
/var/www/discourse/lib/site_settings/db_provider.rb:58:in `table_exists?'
/var/www/discourse/lib/site_settings/db_provider.rb:14:in `all'
/var/www/discourse/lib/site_settings/defaults_provider.rb:30:in `db_all'
/var/www/discourse/lib/site_setting_extension.rb:360:in `block in refresh!'
/var/www/discourse/lib/site_setting_extension.rb:353:in `synchronize'
/var/www/discourse/lib/site_setting_extension.rb:353:in `refresh!'
/var/www/discourse/config/initializers/005-site_settings.rb:20:in `block (2 levels) in <main>'
/var/www/discourse/lib/freedom_patches/rails_multisite.rb:16:in `block in safe_each_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-6.1.0/lib/rails_multisite/connection_management/null_instance.rb:49:in `with_connection'/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-6.1.0/lib/rails_multisite/connection_management/null_instance.rb:36:in `each_connection'/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-6.1.0/lib/rails_multisite/connection_management.rb:21:in `each_connection'
/var/www/discourse/lib/freedom_patches/rails_multisite.rb:9:in `each_active_connection'
/var/www/discourse/lib/freedom_patches/rails_multisite.rb:14:in `safe_each_connection'
/var/www/discourse/config/initializers/005-site_settings.rb:18:in `block in <main>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:407:in `instance_exec'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:407:in `block in make_lambda'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:179:in `block in call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:668:in `block (2 levels) in default_terminator'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:667:in `catch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:667:in `block in default_terminator'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:180:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:559:in `block in invoke_before'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:559:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:559:in `invoke_before'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:109:in `run_callbacks'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/reloader.rb:96:in `prepare!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/application/finisher.rb:74:in `block in <module:Finisher>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/initializable.rb:32:in `instance_exec'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/initializable.rb:32:in `run'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/initializable.rb:61:in `block in run_initializers'
/usr/local/lib/ruby/3.3.0/tsort.rb:231:in `block in tsort_each'
/usr/local/lib/ruby/3.3.0/tsort.rb:353:in `block (2 levels) in each_strongly_connected_component'
/usr/local/lib/ruby/3.3.0/tsort.rb:434:in `each_strongly_connected_component_from'
/usr/local/lib/ruby/3.3.0/tsort.rb:352:in `block in each_strongly_connected_component'
/usr/local/lib/ruby/3.3.0/tsort.rb:350:in `each'
/usr/local/lib/ruby/3.3.0/tsort.rb:350:in `call'
/usr/local/lib/ruby/3.3.0/tsort.rb:350:in `each_strongly_connected_component'
/usr/local/lib/ruby/3.3.0/tsort.rb:229:in `tsort_each'
/usr/local/lib/ruby/3.3.0/tsort.rb:208:in `tsort_each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/initializable.rb:60:in `run_initializers'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/application.rb:435:in `initialize!'
/var/www/discourse/config/environment.rb:7:in `<main>'
/usr/local/lib/ruby/3.3.0/bundled_gems.rb:69:in `require'
/usr/local/lib/ruby/3.3.0/bundled_gems.rb:69:in `block (2 levels) in replace_require'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/bootsnap-1.18.4/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.7.1/lib/zeitwerk/core_ext/kernel.rb:34:in `require'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/application.rb:411:in `require_environment!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/application.rb:559:in `block in run_tasks_blocks'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:281:in `block in execute'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:281:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:281:in `execute'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:219:in `block in invoke_with_call_chain'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:199:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:199:in `invoke_with_call_chain'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:243:in `block in invoke_prerequisites'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:241:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:241:in `invoke_prerequisites'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:218:in `block in invoke_with_call_chain'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:199:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:199:in `invoke_with_call_chain'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:243:in `block in invoke_prerequisites'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:241:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:241:in `invoke_prerequisites'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:218:in `block in invoke_with_call_chain'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:199:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:199:in `invoke_with_call_chain'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:188:in `invoke'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:188:in `invoke_task'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:138:in `block (2 levels) in top_level'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:138:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:138:in `block in top_level'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:147:in `run_with_threads'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:132:in `top_level'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:83:in `block in run'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:214:in `standard_exception_handling'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:80:in `run'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/exe/rake:27:in `<top (required)>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/bin/rake:25:in `load'
/var/www/discourse/vendor/bundle/ruby/3.3.0/bin/rake:25:in `<top (required)>'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli/exec.rb:58:in `load'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli/exec.rb:58:in `kernel_load'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli/exec.rb:23:in `run'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli.rb:455:in `exec'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/vendor/thor/lib/thor/command.rb:28:in `run'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/vendor/thor/lib/thor.rb:527:in `dispatch'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli.rb:35:in `dispatch'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/vendor/thor/lib/thor/base.rb:584:in `start'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli.rb:29:in `start'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/exe/bundle:28:in `block in <top (required)>'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/friendly_errors.rb:117:in `with_friendly_errors'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/exe/bundle:20:in `<top (required)>'
/usr/local/bin/bundle:25:in `load'
/usr/local/bin/bundle:25:in `<main>'
rake aborted!
ActiveRecord::ConnectionNotEstablished: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: No such file or directory (ActiveRecord::ConnectionNotEstablished)
        Is the server running locally and accepting connections on that socket?
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:69:in `rescue in new_client'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:57:in `new_client'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:982:in `connect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:994:in `reconnect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:662:in `block in reconnect!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/concurrency/null_lock.rb:9:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:661:in `reconnect!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:763:in `block in verify!'/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/concurrency/null_lock.rb:9:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:754:in `verify!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:771:in `connect!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:977:in `block in with_raw_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/concurrency/null_lock.rb:9:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:976:in `with_raw_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql/quoting.rb:128:in `quote_string'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract/quoting.rb:76:in `quote'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql/quoting.rb:122:in `quote'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql/schema_statements.rb:1099:in `quoted_scope'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql/schema_statements.rb:1076:in `data_source_sql'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract/schema_statements.rb:60:in `table_exists?'
/var/www/discourse/config/initializers/006-ensure_login_hint.rb:8:in `block in <main>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:407:in `instance_exec'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:407:in `block in make_lambda'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:179:in `block in call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:668:in `block (2 levels) in default_terminator'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:667:in `catch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:667:in `block in default_terminator'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:180:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:559:in `block in invoke_before'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:559:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:559:in `invoke_before'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:109:in `run_callbacks'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/reloader.rb:96:in `prepare!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/application/finisher.rb:74:in `block in <module:Finisher>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/initializable.rb:32:in `instance_exec'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/initializable.rb:32:in `run'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/initializable.rb:61:in `block in run_initializers'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/initializable.rb:60:in `run_initializers'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/application.rb:435:in `initialize!'
/var/www/discourse/config/environment.rb:7:in `<main>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/bootsnap-1.18.4/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.7.1/lib/zeitwerk/core_ext/kernel.rb:34:in `require'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/application.rb:411:in `require_environment!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/application.rb:559:in `block in run_tasks_blocks'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/exe/rake:27:in `<top (required)>'
/usr/local/bin/bundle:25:in `load'
/usr/local/bin/bundle:25:in `<main>'

Caused by:
PG::ConnectionBad: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: No such file or directory (PG::ConnectionBad)
        Is the server running locally and accepting connections on that socket?
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/pg-1.5.4/lib/pg/connection.rb:819:in `connect_start'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/pg-1.5.4/lib/pg/connection.rb:819:in `connect_to_hosts'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/pg-1.5.4/lib/pg/connection.rb:759:in `new'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/pg-1.5.4/lib/pg.rb:63:in `connect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:58:in `new_client'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:982:in `connect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:994:in `reconnect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:662:in `block in reconnect!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/concurrency/null_lock.rb:9:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:661:in `reconnect!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:763:in `block in verify!'/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/concurrency/null_lock.rb:9:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:754:in `verify!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:771:in `connect!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:977:in `block in with_raw_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/concurrency/null_lock.rb:9:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:976:in `with_raw_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql/quoting.rb:128:in `quote_string'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract/quoting.rb:76:in `quote'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql/quoting.rb:122:in `quote'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql/schema_statements.rb:1099:in `quoted_scope'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/postgresql/schema_statements.rb:1076:in `data_source_sql'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract/schema_statements.rb:60:in `table_exists?'
/var/www/discourse/config/initializers/006-ensure_login_hint.rb:8:in `block in <main>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:407:in `instance_exec'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:407:in `block in make_lambda'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:179:in `block in call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:668:in `block (2 levels) in default_terminator'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:667:in `catch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:667:in `block in default_terminator'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:180:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:559:in `block in invoke_before'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:559:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:559:in `invoke_before'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/callbacks.rb:109:in `run_callbacks'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.2.1/lib/active_support/reloader.rb:96:in `prepare!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/application/finisher.rb:74:in `block in <module:Finisher>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/initializable.rb:32:in `instance_exec'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/initializable.rb:32:in `run'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/initializable.rb:61:in `block in run_initializers'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/initializable.rb:60:in `run_initializers'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/application.rb:435:in `initialize!'
/var/www/discourse/config/environment.rb:7:in `<main>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/bootsnap-1.18.4/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/zeitwerk-2.7.1/lib/zeitwerk/core_ext/kernel.rb:34:in `require'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/application.rb:411:in `require_environment!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/application.rb:559:in `block in run_tasks_blocks'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/exe/rake:27:in `<top (required)>'
/usr/local/bin/bundle:25:in `load'
/usr/local/bin/bundle:25:in `<main>'
Tasks: TOP => db:migrate => db:load_config => environment
(See full trace by running task with --trace)
I, [2025-01-05T06:32:34.909125 #1]  INFO -- : gem install ruby-openid -v 2.9.2 -i /var/www/discourse/plugins/discourse-steam-login/gems/3.3.6 --no-document --ignore-dependencies --no-user-install
Successfully installed ruby-openid-2.9.2
1 gem installed
gem install rack-openid -v 1.4.2 -i /var/www/discourse/plugins/discourse-steam-login/gems/3.3.6 --no-document --ignore-dependencies --no-user-install
Successfully installed rack-openid-1.4.2
1 gem installed
gem install omniauth-openid -v 2.0.1 -i /var/www/discourse/plugins/discourse-steam-login/gems/3.3.6 --no-document --ignore-dependencies --no-user-installSuccessfully installed omniauth-openid-2.0.1
1 gem installed
gem install omniauth-steam -v 1.0.6 -i /var/www/discourse/plugins/discourse-steam-login/gems/3.3.6 --no-document --ignore-dependencies --no-user-install
Successfully installed omniauth-steam-1.0.6
1 gem installed

I, [2025-01-05T06:32:34.910102 #1]  INFO -- : Terminating async processes
I, [2025-01-05T06:32:34.910159 #1]  INFO -- : Sending TERM to exec chpst -u redis -U redis /usr/bin/redis-server /etc/redis/redis.conf pid: 87
87:signal-handler (1736058754) Received SIGTERM scheduling shutdown...
87:M 05 Jan 2025 06:32:34.971 # User requested shutdown...
87:M 05 Jan 2025 06:32:34.971 * Saving the final RDB snapshot before exiting.
87:M 05 Jan 2025 06:32:35.116 * DB saved on disk
87:M 05 Jan 2025 06:32:35.116 # Redis is now ready to exit, bye bye...


FAILED
--------------------
Pups::ExecError: cd /var/www/discourse && su discourse -c 'bundle exec rake db:migrate' failed with return #<Process::Status: pid 2178 exit 1>
Location of failure: /usr/local/lib/ruby/gems/3.3.0/gems/pups-1.2.1/lib/pups/exec_command.rb:132:in `spawn'
exec failed with the params {"cd"=>"$home", "tag"=>"migrate", "hook"=>"db_migrate", "cmd"=>["su discourse -c 'bundle exec rake db:migrate'"]}
bootstrap failed with exit code 1
** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one.
./discourse-doctor may help diagnose the problem.
9e8de06a277d5ac57d1a7ef16b9cde5fc6dd11766c456bccc7ea22b90bf80bb9

이렇게 하니 작동하는 것 같습니다. 그리고 앱은 실행 중이라고 표시되지만 웹에서는 접근할 수 없습니다.

아직 도메인 서버와 연결되지 않은 걸까요?

참고:. 원인을 찾은 것 같습니다. IP 주소 변경이 완전히 적용되려면 24시간에서 72시간까지 기다려야 할 수 있습니다. :slightly_frowning_face:

이것이 제가 받는 연결 메시지입니다. 네임서버가 업데이트될 때까지 기다려야 할 것 같습니다.

1개의 좋아요

새 서버로 rsync를 수행할 때 --numeric-ids 옵션이 100% 필수라는 점을 다시 한번 강조하고 싶습니다. 이 옵션을 사용하지 않으면 rsync는 두 호스트 간에 사용자 이름을 일치시키려 시도하게 되며, 이는 Docker 내부의 파일 소유권을 변경시킵니다. 그 결과, 수백만 개의 오류 메시지 속에서 첫 번째 실패 원인을 찾게 되는데, 그 원인은 Postgres가 자신이 소유해야 한다고 생각하는 파일의 소유권을 더 이상 가지고 있지 않아 시작을 거부한 것입니다. 하지만 그 이후에도 수많은 혼란이 뒤따릅니다(Redis가 이미 리스닝 중인 TCP 포트를 다시 바인드하려 시도하는 것, 개와 고양이가 함께 사는 것처럼 엉망이 되는 등) 하여 문제를 진단하기 어렵게 만듭니다.

또한, Discourse가 실제로 만든 백업이 Discourse에 의해 완전히 제어되는 Docker 컨테이너 내에서 실행되어야 함에도 불구하고 정상적으로 작동하지 않을 수 있으며, 실제로 수년 전부터, 이러한 실패 사례가 보고되었음에도 불구하고 아직까지 해결되지 않은 것 같다는 사실은 정말 무서운 일입니다. 그래서 저는 새 하드웨어로 이식하기 위해 rsync를 사용했습니다. Rsync는 작업을 성공적으로 완료했고, 지금은 시간당 스냅샷이 생성되는 미러링된 ZFS 파일시스템에 저장되어 있으며, 매일 원격 백업이 이루어지고 있어 매우 좋습니다. 하지만 재앙 상황에서 Discourse의 자동 백업이 자신을 구해줄 것이라고 믿고 있는 모든 관리자들을 위해 저는 여전히 우려를 표합니다. 그들은 나중에 백업을 사용하려고 할 때 손상된 SQL 인덱스와 어떤 플러그인을 실행 중이었는지에 대해 고개를 갸웃거리게 될 테니까요.

손상된 인덱스 문제에 대해 궁금합니다. 실제로 인덱스가 손상되어 있다면, rsync가 그 잘못된 정보를 새 인스턴스로 그대로 전파하지 않을까요? 백업/복원 과정에서는 적어도 무언가 잘못되었음을 감지할 수 있지 않을까요?

손상된 인덱스를 어떻게 수정하는 것이 최선인지 명확하지 않습니다. PostgreSQL 문서에는 다음과 같이 적혀 있습니다:

사용자 테이블의 인덱스 손상이 의심되는 경우, REINDEX INDEX 또는 REINDEX TABLE을(를) 사용하여 해당 인덱스나 테이블의 모든 인덱스를 다시 구축하면 됩니다.

깊이 파고들지 않아서 단정할 수는 없지만, 공식 백업 방식이 작동하지 않는 SQL 덤프를 생성하거나, 이를 가져오는 과정에서 막을 수 있었을 쇼스토퍼(치명적 장애)가 발생하거나, 데이터베이스가 수년째 깨져 있었지만 rsync로 복사하면 Postgres가 어떻게든 계속 실행되는 것 중 하나일 것입니다.

이론적으로 SQL 인덱스는 쿼리를 빠르게 하기 위한 것일 뿐이죠? 그렇다면 rsync된 시스템은 인덱스를 무시하고 있고, 우리가 아직 눈치채지 못한 작은 비효율이 존재할 수도 있습니다. 정말로 잘 모르겠습니다.

다른 스레드에서의 언급에 따르면, Postgres의 특정 버전에서 문제가 발생했고 이후 버전에서 수정되었다고 하지만, 정확히 어떤 기술적 문제가 있었는지는 알지 못합니다.

그것이 항상 사실인지, 혹은 항상 제대로 작동하는지는 확신할 수 없습니다. 어언 시점에 Docker 컨테이너 내부의 사용자 ID나 그룹 ID가 변경된 것으로 기억합니다. 그래도 --numeric-ids를 시도해 볼 의향은 있습니다.

새 서버 마이그레이션을 수행할 때 저는 다음과 같은 방식으로 PostgreSQL 관련 파일을 제외하고 있습니다:

cd /var/discourse
rsync -rav --numeric-ids =old_ip=:/var/discourse/containers/ /var/discourse/containers/
rsync -rav --numeric-ids =old_ip=:/var/discourse/shared/ /var/discourse/shared/ --exclude log --exclude postgres_* --exclude redis_data --exclude log --exclude tmp --exclude state

그리고 새 머신에 백업 파일을 복원합니다.

네. 깨진 인덱스 문제는 정말 골치 아픈 일이죠. 다만 제가 오랜 기간 동안 이를 경험한 적은 없는 것 같습니다.

네, 맞습니다. 하지만 (생각컨대) 그것들은 값이 고유해야 하는 것을 보장하는 역할도 합니다. 깨진 인덱스는 고유해야 할 값이 여러 레코드에 존재하게 허용합니다. 이는 링크 클릭 추적과 같은 용도로 사용되므로, 오류가 발생해도 특별히 치명적인 문제는 아닙니다.

저는 이 문제에 대해 당신보다 더 주의를 기울였다고 생각합니다. 위 내용은 제 이해를 거의 요약한 것입니다. :person_shrugging: 문제가 PG12에서 있었던 것일까요? 그것이 제가 오랫동안 이 문제를 겪지 않은 이유를 설명할 수 있지만, 제가 확실히 알고 있었는지도, 혹은 기억하는지도 장담할 수 없습니다.

1개의 좋아요

이 문제를 해결하는, 심지어 일괄 처리 가능한 알려진 마법 같은 명령어가 있을까요? 예를 들어 ./launcher enter app를 실행한 후 이 특정 명령어를 실행하면 필요했든 아니든 모든 데이터베이스 인덱스를 다시 빌드해 주는 그런 식으로요.

Discourse의 놀랍고도 무서운 점은 거의 모든 문제를 해결할 수 있는 희귀하고 난해한 마법이 거의 항상 존재한다는 것입니다. 하지만 그 지식을 우연히 발견하는 것은 때로 쉽지 않죠. :slight_smile:

(또한, 네, 이것이 항상 작동하지는 않을 수 있으므로, 제가 그랬던 것보다 덜 확신을 가지고 말해야겠지만… 매핑 파일 소유권을 새 호스트 서버가 가진 것으로 설정하는 것은 분명히 운에 맡기는 수밖에 없으므로, rsync를 실행할 때 Discourse 이미지가 여전히 동일한 사용자 ID 번호를 가지고 있다는 것을 믿고 도박을 하는 것이 더 나을 것입니다.)

다음과 같이 할 수 있습니다.

./launcher enter app
sudo su - postgres
psql

그리고 나서, (편집: 찾아보니 이것이 실제 명령어인 것 같습니다)

REINDEX CONCURRENTLY DATABASE discourse;

이렇게 하면 인덱스를 다시 구축하려고 시도하고, 성공하면 문제가 해결됩니다. 실패하면 중복된 ID를 가진 항목들을 찾아서 삭제해야 합니다. 이 과정은 좀 더 복잡합니다.

3개의 좋아요

그건 더 복잡하네요.

주님, 이게 정말로 사실이었네요! :slight_smile:

제가 한번 시도해 보았습니다. 참고로 저희 Discourse 인스턴스에는 메일링 리스트 아카이브 약 15~20년 치가 가져와져 있습니다. 그래서 다음과 같은 모습의 오래된 게시글들이 아주 많습니다…

…여기서 링크가 엄청나게 많이 나오고, 이전 메일 전체를 인용하는 이메일 답글들(그 링크들을 반복해서 포함하는)과 관련 없는 곳으로 연결되는 링크가 있는 이메일 서명 등이 있습니다.

그러다 어느 시점에 topic_links 테이블이 어긋나기 시작했고, 이미 가지고 있던 링크들에 대해 새로운 행(row)을 만들기 시작했습니다:

예를 들어 다음과 같은 행이 있을 수 있습니다:


  69534 |    18675 |   86333 |    6631 | http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org   | lists.libsdl.org            | f        |               | 2017-03-26 12:13:06.365742 | 2017-03-26 12:13:06.365742 | f          |      0 |              | SDL Info Page                                 | 2017-03-26 13:18:08.491592 | f     | 

이 행은 2017년에 생성되었습니다. 그런데 2024년에 시스템이 id 값이 약 200,000 더 높은 중복 행들을 추가하면서, 이 모든 게시글들에 걸쳐 수백 개의 중복 데이터가 생겼습니다.

그래서 정리할 것이 아주 많습니다.

대략적으로 재인덱싱이 실패하는 것을 기다렸다가, 어떤 것이 출력되는지 확인하고, 중복 행의 ID를 찾아서 URL 문자열을 더 이상 중복되지 않도록 조정하는 방식이었습니다… 시스템이 이미 이 문제를 처리하기 위해 문자열에 **를 반쯤 무작위로 삽입하는 것 같습니다. 저도 그렇게 했습니다. 이 행들이 다른 곳에서 어떻게 참조되고 있는지 전혀 모르기 때문에 행을 그대로 삭제하는 것은 무서웠습니다.

같은 소수의 URL을 반복해서 수정하고 있었기 때문에, 아마도 동일한 주제에 대한 다른 게시글들인 것으로 보입니다. 정말 지루한 작업이었고, 추천하지 않습니다. :slight_smile: 이 작업을 자동화하는 방법을 찾아야 했을 것입니다.

또한 REINDEX의 “CONCURRENTLY” 옵션은 임시 인덱스(이름 뒤에 _ccnew* 문자열이 추가된)를 생성하며, 프로세스가 실패하면 해당 임시 인덱스를 그대로 남겨둡니다. CONCURRENTLY를 사용하여 많은 것을 정리해야 하는 경우, 모든 것을 정리할 때까지 임시 인덱스를 아주 많이 삭제해야 할 것입니다. (또한 저처럼 Postgres를 직접 사용해 본 적이 없다면, REINDEX 명령을 사용할 수 있기 시작하기 전에 \connect discourse; 명령을 먼저 실행해야 했다는 점도 알아두시기 바랍니다.)

저는 아직 이 작업을 진행 중입니다. 상황이 더 나빠지는 것 같지는 않아서 계속 이어서 진행하고 있습니다.

이건 실질적인 도움이라기보다는 막연한 추측에 가깝지만, 몇 가지 아이디어를 제안해 보겠습니다.

먼저, 어떤 인덱스가 깨졌는지를 알았으니 데이터베이스의 모든 인덱스가 아니라 해당 인덱스 하나만 다시 인덱싱할 수 있습니다. 어떻게 해야 하는지에 대한 힌트는 https://ask.discourse.com/ 에 질문해 보세요.

Corrupt indexes in PG12, how do I fix? - #11 by sam 링크에도 몇 가지 힌트가 있습니다.

링크 추적에 대해 크게 신경 쓸 필요가 없다면(어쨌든 새로운 링크가 생성되었을 테니), 중복 항목을 삭제하는 것만으로도 충분합니다.

중복 항목을 찾아낼 수 있는 쿼리를 작성하는 방법이 있을 텐데, 그렇게 하면 한 번에 모두 삭제할 수 있을 것입니다.

이 작업을 완료했고, Postgres(그리고 Discourse!)도 문제없는 것 같습니다.

수동으로 정리하면서, 적절한 경우 ** 패턴을 사용해 URL을 고유하게 만들었습니다. 단순히 중복 항목을 삭제해도 되는 해로운 캐시일 수도 있었지만, 위험을 감수하고 싶지 않았습니다.

제 경우에는 인덱스가 하나뿐이었기 때문에 모든 인덱스를 재구성하는 것은 과잉 대응이었을 수 있지만, 솔직히 모든 문제를 포착했다는 확신이 들었으니 마음이 놓였습니다.

재구성을 여러 번 실패한 후, 각 실행에 약 30초가 걸리며 문제가 하나씩 보고되었는데, 이때 즉시 문제 항목의 전체 목록을 가져오기 위해 사용했던 제 SQL 마법은 다음과 같습니다:

discourse=# select topic_id, post_id, url, COUNT(*) from topic_links GROUP BY topic_id, post_id, url HAVING COUNT(*) > 1 order by topic_id, post_id;
 topic_id | post_id |                          url                          | count 
----------+---------+-------------------------------------------------------+-------
    19200 |   88461 | http://hg.libsdl.org/SDL/rev/**533131e24aeb           |     2
    19207 |   88521 | http://hg.libsdl.org/SDL/rev/44a2e00e7c66             |     2
    19255 |   88683 | http://lists.libsdl.org/__listinfo.cgi/sdl-libsdl.org |     2
    19255 |   88683 | http://lists.libsdl.org/**listinfo.cgi/sdl-libsdl.org |     2
    19523 |   90003 | http://twitter.com/Ironcode_Gaming                    |     2
(5 rows)

(예를 들어, 이 쿼리에서 남은 문제 항목은 5개입니다.)

그 다음 각 게시물을 확인하여 무엇이 있는지, 무엇을 수정해야 하는지 살펴봤습니다:

select * from topic_links where topic_id=19255 and post_id=88683

그리고 그중 하나를 수정했습니다:

update public.topic_links set url='http://lists.libsdl.org/__listinfo.cgi/**sdl-libsdl.org' where id=275100;

수정할 항목이 없도록 될 때까지 반복했습니다. :slight_smile:

내부 조인(inner-join) 마법(또는 아마도 조금의 Ruby)으로 이 모든 것을 하나의 쿼리로 처리할 수도 있었겠지만, 저는 전문가가 아니었고 수동으로 처리하는 데 _수 시간_이 걸리지는 않았습니다. 하지만 분명히 지루한 작업이었습니다. :slight_smile:

그 후 CONCURRENTLY 없이 REINDEX DATABASE discourse;를 실행하여 간단하게 유지했고, 이전에 놓친 몇 개의 ccnew* 인덱스를 제거한 후 모든 것이 정상화되었습니다.

사이트는 내내 라이브 상태였으며, 다운타임은 없었습니다.

이것이 _필요_했는지는 모르겠지만, 제 데이터가 조금 더 안전해졌다고 확실히 느끼고 있으며, 예고 없이 찾아올 미래의 재앙으로 치닫고 있다는 느낌은 없습니다.

이 문제를 해결하는 데 올바른 방향으로 이끌어준 @pfaffman님께 감사드립니다.

2개의 좋아요