2013-12-31 4 views
3

У меня есть процесс ETL, который постепенно наращивает таблицы размеров в RedShift. Он выполняет действия в следующем порядке:Почему неблокированная блокировка таблицы освобождается до завершения транзакции в RedShift?

  1. начинается транзакция
  2. Создает таблицу staging_foo как обув
  3. копирует данные из внешнего источника в staging_foo
  4. выполняет массовая вставка/обновление/удаление на обув так, что Совпадает staging_foo
  5. падение staging_foo
  6. фиксации транзакции

Индивидуально этот процесс работает, но для обеспечения непрерывного потокового обновления до foo и избыточности в случае сбоя у меня есть несколько экземпляров процесса, выполняемого одновременно. И когда это случается, я иногда получаю параллельные ошибки сериализации. Это связано с тем, что оба процесса воспроизводят одни и те же изменения в foo от foo_staging в перекрывающихся транзакциях.

Что происходит, так это то, что первый процесс создает таблицу staging_foo, а второй процесс блокируется при попытке создать таблицу с тем же именем (это то, что я хочу). Когда первый процесс совершает транзакцию (которая может занять несколько секунд), я обнаруживаю, что второй процесс разблокируется до завершения коммита. Таким образом, похоже, что получение моментального снимка таблицы foo до фиксации происходит, что приводит к сбою вставки/обновления/удаления (некоторые из которых могут быть избыточными).

Я теоретизировать на основе документации http://docs.aws.amazon.com/redshift/latest/dg/c_serial_isolation.html, где он говорит:

Одновременные операции невидимы друг к другу; они не могут обнаружить изменения друг друга. Каждая параллельная транзакция будет создавать моментальный снимок базы данных в начале транзакции. Снимки базы данных создаются в транзакции при первом вхождении большинства операторов SELECT, таких как команды DML, такие как COPY, DELETE, INSERT, UPDATE и TRUNCATE, а также следующие команды DDL:

ALTER TABLE (для добавления или удаления столбцов)

CREATE TABLE

DROP TABLE

TRUNCATE ТАБЛИЦА

документация цитированной выше несколько сбивает с толку для меня, потому что вначале говорится, что моментальный снимок будет создан в начале транзакции, но впоследствии будет сказано, что моментальный снимок будет создан только при первом появлении некоторых конкретных операций DML/DDL.

Я не хочу делать глубокую копию, где я заменяю foo вместо поэтапного обновления. У меня есть другие процессы, которые постоянно запрашивают эту таблицу, поэтому никогда не бывает времени, когда я могу ее заменить без перерыва. Другой вопрос задает аналогичный вопрос для глубокой копии, но он не будет работать для меня: How can I ensure synchronous DDL operations on a table that is being replaced?

Есть ли способ для выполнения моих операций таким образом, чтобы я мог избежать параллельных ошибок сериализации?Мне нужно убедиться, что доступ для чтения доступен для foo, поэтому я не могу LOCK этой таблицы.

ответ

3

ОК, Postgres (и, следовательно, Redshift [более или менее]) использует MVCC (Multi Version Concurrency Control) для изоляции транзакции вместо db/table/row/page locking model (as seen in SQL Server, MySQL и т. Д.). Упрощенно каждая транзакция работает с данными , как она существовала при начале транзакции.

Итак, ваш комментарий «У меня несколько экземпляров процесса, запущенного в одно и то же время», объясняет проблему. Если процесс 2 начинается, когда выполняется процесс 1, то процесс 2 не имеет видимости результатов процесса 1.

Смежные вопросы