Heroku Postgis - django releases fail with: relation "spatial_ref_sys" does not exist

С тех пор как Heroku изменил управление схемой расширений (https://devcenter.heroku.com/changelog-items/2446) развертывание нашего существующего приложения django 4.0 завершается со следующей ошибкой:

Traceback (most recent call last):
  File "/app/.heroku/python/lib/python3.9/site-packages/django/db/backends/utils.py", line 87, in _execute
    return self.cursor.execute(sql)
psycopg2.errors.UndefinedTable: relation "spatial_ref_sys" does not exist
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "/app/manage.py", line 22, in <module>
    main()
  File "/app/manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/app/.heroku/python/lib/python3.9/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line
    utility.execute()
  File "/app/.heroku/python/lib/python3.9/site-packages/django/core/management/__init__.py", line 440, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/app/.heroku/python/lib/python3.9/site-packages/django/core/management/base.py", line 414, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/app/.heroku/python/lib/python3.9/site-packages/django/core/management/base.py", line 460, in execute
    output = self.handle(*args, **options)
  File "/app/.heroku/python/lib/python3.9/site-packages/django/core/management/base.py", line 98, in wrapped
    res = handle_func(*args, **kwargs)
  File "/app/.heroku/python/lib/python3.9/site-packages/django/core/management/commands/migrate.py", line 106, in handle
    connection.prepare_database()
  File "/app/.heroku/python/lib/python3.9/site-packages/django/contrib/gis/db/backends/postgis/base.py", line 26, in prepare_database
    cursor.execute("CREATE EXTENSION IF NOT EXISTS postgis")
  File "/app/.heroku/python/lib/python3.9/site-packages/sentry_sdk/integrations/django/__init__.py", line 544, in execute
    return real_execute(self, sql, params)
  File "/app/.heroku/python/lib/python3.9/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(
  File "/app/.heroku/python/lib/python3.9/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/app/.heroku/python/lib/python3.9/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "/app/.heroku/python/lib/python3.9/site-packages/django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/app/.heroku/python/lib/python3.9/site-packages/django/db/backends/utils.py", line 87, in _execute
    return self.cursor.execute(sql)
django.db.utils.ProgrammingError: relation "spatial_ref_sys" does not exist

Кто-нибудь сталкивался с такой же проблемой? Есть ли обходной путь, кроме переустановки расширения postgis?

Я отслеживаю очень похожую проблему. Я связался с компанией heroku. В моей предыдущей ошибке упоминалось расширение pgaudit, теперь я вижу ту же ошибку, что и вы. Я сообщу здесь, если узнаю о решении проблемы.

System check identified no issues (5 silenced).
Traceback (most recent call last):
File "/app/.heroku/python/lib/python3.10/site-packages/django/db/backends/utils.py", line 87, in _execute
return self.cursor.execute(sql)
psycopg2.errors.UndefinedTable: relation "spatial_ref_sys" does not exist
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/app/manage.py", line 40, in
main()
File "/app/manage.py", line 36, in main
execute_from_command_line(sys.argv)
File "/app/.heroku/python/lib/python3.10/site-packages/django/core/management/init.py", line 446, in execute_from_command_line
utility.execute()
File "/app/.heroku/python/lib/python3.10/site-packages/django/core/management/init.py", line 440, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/app/.heroku/python/lib/python3.10/site-packages/django/core/management/base.py", line 414, in run_from_argv
self.execute(*args, **cmd_options)
File "/app/.heroku/python/lib/python3.10/site-packages/django/core/management/base.py", line 460, in execute
output = self.handle(*args, **options)
File "/app/.heroku/python/lib/python3.10/site-packages/django/core/management/base.py", line 98, in wrapped
res = handle_func(*args, **kwargs)
File "/app/.heroku/python/lib/python3.10/site-packages/django/core/management/commands/migrate.py", line 106, in handle
connection.prepare_database()
File "/app/.heroku/python/lib/python3.10/site-packages/psqlextra/backend/base.py", line 32, in prepare_database
super().prepare_database()
File "/app/.heroku/python/lib/python3.10/site-packages/django/contrib/gis/db/backends/postgis/base.py", line 26, in prepare_database
cursor.execute("CREATE EXTENSION IF NOT EXISTS postgis")
File "/app/.heroku/python/lib/python3.10/site-packages/sentry_sdk/integrations/django/init.py", line 544, in execute
return real_execute(self, sql, params)
File "/app/.heroku/python/lib/python3.10/site-packages/django/db/backends/utils.py", line 67, in execute
return self._execute_with_wrappers(
File "/app/.heroku/python/lib/python3.10/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/app/.heroku/python/lib/python3.10/site-packages/django_read_only/init.py", line 74, in blocker
return execute(sql, params, many, context)
File "/app/.heroku/python/lib/python3.10/site-packages/django/db/backends/utils.py", line 84, in _execute
with self.db.wrap_database_errors:
File "/app/.heroku/python/lib/python3.10/site-packages/django/db/utils.py", line 91, in exit
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/app/.heroku/python/lib/python3.10/site-packages/django/db/backends/utils.py", line 87, in _execute
return self.cursor.execute(sql)
django.db.utils.ProgrammingError: relation "spatial_ref_sys" does not exist
Sentry is attempting to send 2 pending error messages
Waiting up to 2 seconds
Press Ctrl-C to quit

Наша команда также столкнулась с этой проблемой сегодня днем

Перед этой ошибкой мы также получили ошибку pgaudit stack is not empty, которая потребовала, чтобы я вручную перевел наши базы данных в режим обслуживания для их ротации. https://devcenter.heroku.com/articles/data-maintenance-cli-commands#heroku-data-maintenances-schedule. Эта статья помогла мне обойти первую проблему, но теперь я нахожусь в той же лодке с ошибкой spatial_ref_sys.

Моя команда тоже столкнулась с этой проблемой. Мы не могли ждать, пока Heroku исправит ситуацию, поэтому сделали небольшую операцию. Это не подходит для всех, но поскольку мы используем PostGIS довольно незначительно, это было не так уж плохо.

Вот мой контрольный список для каждой затронутой базы данных:

  • резервное копирование базы данных
  • включите режим обслуживания
  • создайте новые примитивные float колонки во всех таблицах, которые использовали geography типы для хранения необработанных данных lat / lng
  • .
  • запишите значения из полей geography в новые колонки
  • .
  • отбросьте расширение postgis: DROP EXTENSION postgis CASCADE;
  • восстановить расширение: CREATE EXTENSION IF NOT EXISTS postgis;
  • воссоздайте наши geography поля и заполните их из новых столбцов
  • .
  • отбросьте новые временные колонки
  • восстановить соответствующие индексы

Пока все хорошо.

Мы также столкнулись с этой проблемой при попытке использовать heroku pg:backups:restore и heroku pg:copy - существующие снимки резервных копий не могут быть восстановлены, если они содержат установленные расширения.

Как и все здесь, было проведено техническое обслуживание, чтобы исправить первую проблему, но теперь у нас есть вторая проблема:

django.db.utils.ProgrammingError: relation "spatial_ref_sys" does not exist

Есть ли у вас какие-либо новости от Heroku по этому поводу? Я знаю, что они сейчас работают над этим, но, может быть, они дали вам какие-то обновления?

Вот обходной путь, который я придумал для наших обзорных приложений, использующих резервное копирование базы данных, через pg:backups:restore (возможно, вам захочется включить обслуживание, если вы работаете с производственной базой данных):

  1. Скопируйте локально базу данных приложения обзора (которая была недавно восстановлена с помощью pg:backups:restore, так что вы получите все данные): heroku pg:pull [Database URL] localdb -a [app-name]

  2. Установите конфигурацию вашей базы данных приложения для использования localdb, затем подключитесь к psql и выполните: ALTER EXTENSION "hstore" SET SCHEMA heroku_ext;. Выполните эту команду для всех существующих расширений.

Чтобы перечислить все доступные расширения, которые вы извлекли, выполните \dx. Вам не нужно изменять plpgsql это родное для PostgreSQL

Это будет работать, потому что локально у вас есть все привилегии.

  1. вытолкните эту версию обратно в ваше приложение обзора: heroku pg:push mylocaldb [Database URL] -a [app-name] ==> Для выполнения этой операции ваша база данных должна быть пустой. Вы можете попробовать эту операцию на свежем приложении обзора с пустыми данными. Таким образом, оно может стать вашей новой базой для всех приложений обзора

    .
  2. Убедитесь, что все работает как ожидалось (данные правильно восстановлены). Затем вы можете создать новый дамп базы данных через pg:backups:capture и использовать его в качестве резервной копии базы данных для всех ваших новых приложений для рецензирования.

    .

Источник: https://devcenter.heroku.com/articles/managing-heroku-postgres-using-cli

Мне также пришлось сделать это, потому что, например, отключение расширения hstore и повторное его включение не было приемлемым вариантом для нашего случая.

Я обошел это, переписав движок postgis/base.py, я поместил следующее в мое приложение под db/base.py

from django.contrib.gis.db.backends.postgis.base import (
     DatabaseWrapper as PostGISDatabaseWrapper,
)

class DatabaseWrapper(PostGISDatabaseWrapper):
    def prepare_database(self):
        # This is the overwrite - we don't want to call the
        # super() because of a faulty extension creation
     pass

Тогда в настройках я просто указал DATABASES["engine"] = "app.db"

Это не поможет с резервными копиями, но, по крайней мере, я смогу выпустить их снова.

Кто-нибудь что-нибудь слышал? Мы застряли на том же вопросе.

В нашем случае postgis при попытке обходного пути ALTER EXTENSION postgis SET SCHEMA heroku_ext выдавал ошибку о том, что не разрешено перемещать схемы, поэтому в итоге нам пришлось сделать это.

UPDATE pg_extension
  SET extrelocatable = true
    WHERE extname = 'postgis';

ALTER EXTENSION "postgis" SET SCHEMA "heroku_ext";

UPDATE pg_extension
  SET extrelocatable = false
    WHERE extname = 'postgis';

Команда Heroku наконец-то решила проблему :)

У меня есть решение, которое не требует изменений кодовой базы и может быть выполнено полностью через Heroku CLI

  1. Используйте инструмент Heroku datastore durability tool для создания резервной копии на исходной базы данных или heroku pg:backups:capture -a <SOURCE_APP>.
  2. Определите, какие расширения pg использует база данных (можно проверить из psql с помощью \dx)
  3. создайте строку расширений, разделенную запятыми (например:fuzzystrmatch,pg_stat_statements,pg_trgm,pgcrypto,plpgsql,unaccent,uuid-ossp')
  4. Убедитесь, что ваш Heroku CLI обновлен по крайней мере до версии 7.63.0 (используйте heroku update для обновления)
  5. Запустите это:
    heroku pg:backups:restore $(heroku pg:backups public-url -a <SOURCE_APP>) DATABASE_URL --extensions '<EXTENSIONS>' -a <TARGET_APP>
    
  6. Переустановите дино на TARGET_APP
Вернуться на верх