1 августа 2022 г. компания Heroku изменила управление схемой расширения PostgreSQL. (https://devcenter.heroku.com/changelog-items/2446)
С тех пор каждое развертывание нашего существующего приложения django 4.0 в Heroku терпит неудачу на этапе выпуска, сборка завершается успешно.
Кто-нибудь сталкивался с такой же проблемой? Есть ли обходной путь для отправки новой версии в Heroku, кроме переустановки расширения postgis?
Если я правильно понимаю изменения, Heroku добавил схему под названием «heroku_ext» для вновь созданных расширений. Поскольку расширение уже существует в нашем случае, оно не должно быть затронуто.
All currently installed extensions will continue to work as intended.
Следуя полным журналам выпуска через git push:
git push staging develop:master
Gesamt 0 (Delta 0), Wiederverwendet 0 (Delta 0), Pack wiederverwendet 0
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Building on the Heroku-20 stack
remote: -----> Using buildpacks:
remote: 1. https://github.com/heroku/heroku-geo-buildpack.git
remote: 2. heroku/python
remote: -----> Geo Packages (GDAL/GEOS/PROJ) app detected
remote: -----> Installing GDAL-2.4.0
remote: -----> Installing GEOS-3.7.2
remote: -----> Installing PROJ-5.2.0
remote: -----> Python app detected
remote: -----> Using Python version specified in runtime.txt
remote: -----> No change in requirements detected, installing from cache
remote: -----> Using cached install of python-3.9.13
remote: -----> Installing pip 22.1.2, setuptools 60.10.0 and wheel 0.37.1
remote: -----> Installing SQLite3
remote: -----> Installing requirements with pip
remote: -----> Skipping Django collectstatic since the env var DISABLE_COLLECTSTATIC is set.
remote: -----> Discovering process types
remote: Procfile declares types -> release, web, worker
remote:
remote: -----> Compressing...
remote: Done: 156.1M
remote: -----> Launching...
remote: ! Release command declared: this new release will not be available until the command succeeds.
remote: Released v123
remote: https://myherokuapp.herokuapp.com/ deployed to Heroku
remote:
remote: This app is using the Heroku-20 stack, however a newer stack is available.
remote: To upgrade to Heroku-22, see:
remote: https://devcenter.heroku.com/articles/upgrading-to-the-latest-stack
remote:
remote: Verifying deploy... done.
remote: Running release command...
remote:
remote: Traceback (most recent call last):
remote: File "/app/.heroku/python/lib/python3.9/site-packages/django/db/backends/utils.py", line 87, in _execute
remote: return self.cursor.execute(sql)
remote: psycopg2.errors.UndefinedTable: relation "spatial_ref_sys" does not exist
remote:
remote:
remote: The above exception was the direct cause of the following exception:
remote:
remote: Traceback (most recent call last):
remote: File "/app/manage.py", line 22, in <module>
remote: main()
remote: File "/app/manage.py", line 18, in main
remote: execute_from_command_line(sys.argv)
remote: File "/app/.heroku/python/lib/python3.9/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line
remote: utility.execute()
remote: File "/app/.heroku/python/lib/python3.9/site-packages/django/core/management/__init__.py", line 440, in execute
remote: self.fetch_command(subcommand).run_from_argv(self.argv)
remote: File "/app/.heroku/python/lib/python3.9/site-packages/django/core/management/base.py", line 414, in run_from_argv
remote: self.execute(*args, **cmd_options)
remote: File "/app/.heroku/python/lib/python3.9/site-packages/django/core/management/base.py", line 460, in execute
remote: output = self.handle(*args, **options)
remote: File "/app/.heroku/python/lib/python3.9/site-packages/django/core/management/base.py", line 98, in wrapped
remote: res = handle_func(*args, **kwargs)
remote: File "/app/.heroku/python/lib/python3.9/site-packages/django/core/management/commands/migrate.py", line 106, in handle
remote: connection.prepare_database()
remote: File "/app/.heroku/python/lib/python3.9/site-packages/django/contrib/gis/db/backends/postgis/base.py", line 26, in prepare_database
remote: cursor.execute("CREATE EXTENSION IF NOT EXISTS postgis")
remote: File "/app/.heroku/python/lib/python3.9/site-packages/sentry_sdk/integrations/django/__init__.py", line 544, in execute
remote: return real_execute(self, sql, params)
remote: File "/app/.heroku/python/lib/python3.9/site-packages/django/db/backends/utils.py", line 67, in execute
remote: return self._execute_with_wrappers(
remote: File "/app/.heroku/python/lib/python3.9/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
remote: return executor(sql, params, many, context)
remote: File "/app/.heroku/python/lib/python3.9/site-packages/django/db/backends/utils.py", line 89, in _execute
remote: return self.cursor.execute(sql, params)
remote: File "/app/.heroku/python/lib/python3.9/site-packages/django/db/utils.py", line 91, in __exit__
remote: raise dj_exc_value.with_traceback(traceback) from exc_value
remote: File "/app/.heroku/python/lib/python3.9/site-packages/django/db/backends/utils.py", line 87, in _execute
remote: return self.cursor.execute(sql)
remote: django.db.utils.ProgrammingError: relation "spatial_ref_sys" does not exist
remote:
remote: Sentry is attempting to send 2 pending error messages
remote: Waiting up to 2 seconds
remote: Press Ctrl-C to quit
remote: Waiting for release.... failed.
To https://git.heroku.com/myherokuapp
🤔 А знаете ли вы, что...
В Python можно легко работать с базами данных, такими как SQLite и MySQL.
Я отслеживаю очень похожую проблему. Я был в контакте с героку. В моей предыдущей ошибке упоминалось расширение 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
Эта статья помогла мне обойти первую проблему, но теперь я нахожусь в той же лодке с ошибкой space_ref_sys.
Моя команда тоже столкнулась с этим. Не могли дождаться, пока Heroku исправят, поэтому мы сделали небольшую хирургическую операцию. Не для всех применимо, но так как мы мало используем PostGIS, это не так уж и плохо.
Это был мой контрольный список для каждой затронутой базы данных:
float
во всех таблицах, которые использовали типы geography
для хранения необработанных данных широты / долготыgeography
в новые столбцыDROP EXTENSION postgis CASCADE;
CREATE EXTENSION IF NOT EXISTS postgis;
geography
и заполните их из новых столбцовВсе идет нормально.
Мы также столкнулись с этой проблемой при попытке использовать heroku pg:backups:restore
и heroku pg:copy
— существующие снимки резервных копий нельзя восстановить, если они содержат установленные расширения.
Вот обходной путь, который я придумал для наших обзорных приложений, использующих резервную копию базы данных, через pg:backups:restore
(может потребоваться включить техническое обслуживание, если вы манипулируете производственной базой данных):
Скопируйте локально базу данных приложения для проверки (та, которая была недавно восстановлена с помощью pg:backups:restore
, чтобы получить все данные): heroku pg:pull [Database URL] localdb -a [app-name]
Настройте конфигурацию базы данных приложения на использование localdb
, затем подключитесь к psql и выполните: ALTER EXTENSION "hstore" SET SCHEMA heroku_ext;
. Запустите эту команду для всех ваших существующих расширений.
Чтобы просмотреть все доступные расширения, которые вы вытащили, запустите \dx
. Вам не нужно ничего менять plpgsql
он встроен в PostgreSQL
Это будет работать, потому что локально у вас есть все привилегии.
отправьте эту версию обратно в приложение для проверки: heroku pg:push mylocaldb [Database URL] -a [app-name]
==> Для этого ваша база данных должна быть пустой. Вы можете попробовать эту операцию на свежем приложении обзора с пустыми данными. таким образом, он может стать вашей новой базой для всех обзорных приложений.
Убедитесь, что все работает как положено (данные правильно восстановлены). Затем вы можете создать новый дамп базы данных с помощью 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"
Это не поможет с резервными копиями, но, по крайней мере, я могу снова выпустить.
Мы использовали этот обходной путь, предоставленный @chedli https://stackoverflow.com/a/73219273/840568.
Но в нашем случае 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';