#postgresql
#postgresql
Вопрос:
хорошо — мы обнаружили ошибку в одной из наших систем, когда материализованные представления обновляются для разных данных, в зависимости от того, какая система вызвала обновление.
Это оказалось проблемой с настройками даты клиента — это зависит от часового пояса пользователя.
Это большой риск. Я знаю, что для каждого поля мы можем переопределить настройки, но это сложно, потому что представления используют другие представления, а преобразования / вычисления даты происходят в любом месте иерархии представлений, поэтому мы не можем гарантировать, что вычисления, специфичные для клиента, не пройдут.
Есть ли какой-либо способ, которым мы можем встроить что-то в определение представления, которое устанавливает текущий часовой пояс для всего представления, поэтому не имеет значения, кто выполняет обновление, оно всегда будет давать один и тот же результат?
Я пробовал это — но это не работает:( — но хочу что-то вроде этого:
create materialized view blah as (
set timezone to 'Australia/Brisbane';
select now())
Комментарии:
1. Являются ли типы полей для временных меток в представлениях
timestamp
илиtimestamptz
?2. вот в чем дело — мы говорим о сотнях полей в сотнях таблиц с большой иерархией представлений поверх представлений поверх представлений, включая буквально каждую комбинацию типа даты / метки времени. Также у меня нет контроля над таблицами или структурами таблиц — все они уже существуют, поэтому мне нужно решить проблему для новых представлений. На данный момент я подключаю вышеупомянутый установленный часовой пояс везде, где представления вызываются в коде … и это работает… но кто-то забудет.
3. Ну, вы не можете делать то, что вы показываете выше. Разве невозможно установить часовой пояс сервера на ‘Австралия / Брисбен’ глобально?
4. но в этом весь смысл — это зависит от часового пояса клиента , а не от сервера — если бы он использовал часовой пояс сервера, проблем не было бы. Проблема возникает из-за того, что когда разные люди запускают команду «обновить представление», мы получаем разные значения в таблице
5. Я не понимаю. Если все работают на одном сервере, то используемый часовой пояс будет любым
show timezone
, что возвращает. Оговорка в том, что люди / клиенты могут выдаватьSET time zone ...
или эквивалент, чтобы изменить его для сеанса. Это то, что происходит?
Ответ №1:
Если вы кодируете свое материализованное представление так, чтобы оно зависело от текущей настройки параметров базы данных, у вас проблемы, потому что многие из них могут быть изменены на уровне сеанса. Не делайте этого.
В текущем случае избегайте всего, что приводит date
или timestamp without timezone
к timestamp with time zone
или наоборот, потому timezone
что будет тайно входить в любые такие преобразования.
Всегда указывайте часовой пояс явно:
- чтобы преобразовать из
date
илиtimestamp
вtimestamp with time zone
, используйтеcurrent_date AT TIME ZONE 'whatever'
- чтобы преобразовать из
timestamp with time zone
вdate
илиtimestamp
, используйтеcurrent_timestamp AT TIME ZONE 'whatever'
Вызываются оба оператора AT TIME ZONE
, но они разные.
Я вижу, что ваша проблема заключается в том, что существует большое количество ранее существовавших определений представлений, которые не соответствуют этому принципу. Возможно, вам сойдет с рук что-то вроде:
WITH setzone AS (
SELECT set_config('timezone', 'UTC', TRUE)
)
SELECT /* your query */;
Но вам нужно изменить запрос так, чтобы он ссылался setzone
на что-то в запросе (вы могли CROSS JOIN
бы это сделать), чтобы он был выполнен.
Комментарии:
1. это с блоком кажется именно тем, что я искал, если это сработает — огромное спасибо!
2. боже — это сработало — спасибо!!! с помощью setzone как (выберите set_config(‘часовой пояс’, ‘Австралия / Брисбен’, TRUE), now() как refreshed_at ) выберите refreshed_at, …