Почему этот запрос выбора Postgres работает в локальном контейнере Docker, но не в Amazon RDS Postgres?

У моей команды есть локальная среда разработки, содержащая приложение Ruby on Rails, которое подключается к базе данных Postgres, чтобы получить некоторую информацию об аэропортах и ​​использовать ее для дальнейших запросов. Локальная среда предназначена для дублирования нашей производственной среды (обе работают в одних и тех же контейнерах докеров).

Локальный контейнер Postgres использует официальный контейнер Postgres: 9.6-alpine, который можно найти здесь: https://hub.docker.com/_/postgres/

Рассматриваемый запрос:

SELECT airports.iata FROM "routes" INNER JOIN "regions" ON "regions"."id" = "routes"."origin_id" INNER JOIN "airports_regions" ON "airports_regions"."region_id" = "regions"."id" INNER JOIN "airports" ON "airports"."id" = "airports_regions"."airport_id";

Выполнение локального запроса

  1. Приведенная выше команда выполняется правильно, когда вызывается нашим приложением rails локально.
  2. Я также могу запустить команду с помощью psql после "docker exec -it'ing" в контейнере Postgres локально.

Выполнение запросов Amazon RDS Postgres

  1. В процессе производства наше приложение Rails пытается выполнить рассматриваемый запрос, но возвращает пустой набор данных: {}

Следует отметить, что он успешно подключается к БД и «успешно» выполняет запрос после правильной аутентификации, поэтому на самом деле проблема здесь в том, что запрос не возвращает / не соответствует данным.

  1. Когда я вручную подключаюсь к нашей базе данных Amazon RDS Postgres с помощью psql, я могу правильно пройти аутентификацию и выполнить запрос, но снова получаю результат null / {}. Все остальные запросы работают.

В обоих вышеупомянутых случаях запрос выполняется правильно. При выполнении вручную он, в частности, возвращает следующее:

iata 
------ 
(0 rows)

Другие интересные факты

  1. Укажите локальный контейнер рельсов в производственной RDS Postgres - Результат: Postgres возвращает {}, даже если контейнеры Postgres МОГУТ выполнить тот же запрос и вернуть ожидаемый список данных при указании на локальную БД. Возвращаемый результат в этом случае воспроизводит производственное поведение: {}
  2. Подключитесь по SSH к инстансу Amazon EC2, подключенному к базе данных RDS в той же группе VPC / Security, и выполните указанную выше команду, чтобы убедиться, что это не проблема с разрешениями. Результат: То же, что и удаленный запрос: {}
  3. Подсчет таблицы в обоих экземплярах (оба возвращают одинаковый результат ~ 5880): $ SELECT COUNT (*) FROM airport;
  4. Listing tables возвращает идентичный список таблиц как в Amazon RDS, так и в локальном Postgres.

Движение вперед

На данный момент я исхожу из предположения, что должны быть различия между тем, как Amazon RDS для Postgres обрабатывает данные и локальный Postgres 9.6 db, но я не смог найти никаких указаний на это в le google. Надеюсь, кто-то сталкивался с чем-то подобным.

Версии Postgres

ВЫБРАТЬ версию (); возвращает следующее:

Версия RDS Postgres

PostgreSQL 9.6.2 на x86_64-pc-linux-gnu, скомпилирован gcc (GCC) 4.8.2 20140120 (Red Hat 4.8.2-16), 64-бит (1 строка)

Локальная версия Postgres

PostgreSQL 9.6.3 на x86_64-pc-linux-musl, скомпилирован gcc (Alpine 6.2.1) 6.2.1 20160822, 64-бит (1 строка)

Предложения StackOverflow с результатами

От @Aleroot Изменить запрос на:

SELECT a.iata FROM routes ru JOIN regions re ON re.id = ru.origin_id JOIN airports_regions ar ON ar.region_id = re.id JOIN airports a ON a.id = ar.airport_id;

Результат: (То же)

 iata 
------
(0 rows)

person Necevil    schedule 17.10.2017    source источник
comment
как у вас ssh к RDS? ..   -  person Vao Tsun    schedule 17.10.2017
comment
@vao Вы не можете подключиться к RDS по SSH, но вы можете подключиться по SSH к экземпляру ec2, подключенному к RDS, а затем использовать команды psql для подключения к БД, как только вы войдете в экземпляр ec2, который находится в группе виртуального частного облака / безопасности (это ближе всего, насколько я знаю).   -  person Necevil    schedule 17.10.2017
comment
просто ssh to ec2 / rds выглядит плохо - извините за разборчивость   -  person Vao Tsun    schedule 17.10.2017
comment
любое внутреннее соединение с несоответствующими идентификаторами вырезанных строк - поэтому недостаточно сравнить количество в аэропортах ... попробуйте заменить на внешние соединения, чтобы увидеть - может быть, в какой-то таблице отсутствуют совпадения для аэропортов? ..   -  person Vao Tsun    schedule 17.10.2017
comment
Вы уверены, что у вас такой же набор данных? Можете ли вы поделиться схемой для соответствующих таблиц? Какой тип идентификаторов? Что-нибудь особенное в них, например, чувствительность к разным условиям? Это было бы необычно для идентификатора, но вы никогда не знаете ... Пробовали ли вы удалять таблицы по одной из запроса, чтобы увидеть, в какой момент он терпит неудачу (или начинает что-то возвращать)?   -  person jcaron    schedule 17.10.2017
comment
@VaoTsun Я заменил его на Left Outer Join и смог вернуть полный список аэропортов (5880), используя следующий запрос. Количество аэропортов, возвращаемых каждым запросом (локальным и RDS), было одинаковым: ВЫБЕРИТЕ airport.iata ИЗ маршрутов ПРАВИЛЬНО СОЕДИНЯЙТЕ регионы НА регионах.id = routes.origin_id ВНУТРЕННЕЕ СОЕДИНЯЙТЕ аэропорты_регионы ВКЛЮЧАЙТЕ аэропорты_regions.region_id = регионы.id ПРАВО СОЕДИНЯЙТЕ аэропорты ВКЛ. airport.id = airport_regions.airport_id;   -  person Necevil    schedule 17.10.2017
comment
поэтому один / несколько регионов, airport_regions, routes имеют разные строки, сравнивающие локальные и docker dbs   -  person Vao Tsun    schedule 17.10.2017
comment
@VaoTsun, ты прав. Если вы хотите опубликовать ответ о выполнении выборок в каждой таблице индивидуально, я приму его, после выполнения выборок в каждой из таблиц локальная копия должным образом вернула результаты для всего, в то время как некоторые из промежуточных таблиц отношений отсутствовали в производстве.   -  person Necevil    schedule 17.10.2017
comment
@Necevil Я так и сделал. Спасибо.   -  person Vao Tsun    schedule 17.10.2017


Ответы (2)


как мы говорили в комментариях, вы можете проверить, не повлияли ли на результат другие таблицы. Изменение INNER JOIN на OUTER JOIN добавит строки с нулями для отсутствующих ключей, таким образом, количество строк в таблице аэропортов будет заполнено. Либо по результату, либо просто путем проверки счетчиков в regions, airports_regions, routes таблицах должно быть выявлено различие между RDS и локальными базами данных.

person Vao Tsun    schedule 17.10.2017

Поскольку комментарий @VaoTsun изначально привел меня к правильному пути, я принял его ответ (также найденный здесь).

Настоящий вопрос, который я должен был задать, на самом деле сводился к следующему: «Как я могу убедиться, что дамп БД, который я импортировал в Amazon RDS Postgres, не поврежден?»

Большая часть путаницы здесь возникла из-за того, что Amazon RDS не выдает ошибок при импортировании дампа и что веб-часть моего приложения Rails правильно отображает почти все данные.

Это произошло из-за того, что большинство таблиц были импортированы правильно со всеми данными, и ВСЕ таблицы были созданы. Поэтому перечисление таблиц / схемы привело к тому, что все выглядело правильно, и все запросы ко всем таблицам, кроме одной, дали правильные ответы.

Я, наконец, вернулся и выбрал все в каждой таблице в базе данных: SELECT * FROM each_table_name;

Одна конкретная таблица не вернула результатов в удаленной базе данных RDS, в то время как ожидаемые результаты были возвращены локально. Как только это произошло, я удалил базу данных из Amazon RDS и повторно импортировал все. Во время импорта ошибок нет (опять же, как и в прошлый раз), но на этот раз все таблицы существуют с данными после выбора всех в каждой таблице один за другим для проверки правильности импортированных данных.

person Necevil    schedule 17.10.2017