Я хочу замінити весь вміст таблиці, не впливаючи на будь-які вхідні SELECTзаяви під час процесу.
Випадок використання - мати таблицю, в якій зберігається інформація про поштові скриньки, яка регулярно витягується, і її потрібно зберігати в таблиці PostgreSQL. Є багато клієнтів, які використовують додаток, який постійно запитує ту саму таблицю.
Зазвичай я б робив щось на кшталт (вхідний псевдокод) ...
BEGIN TRANSACTION
TRUNCATE TABLE
INSERT INTO
COMMIT
Але, на жаль, таблицю неможливо прочитати під час цього процесу; за рахунок часу, необхідного INSERT INTOдля його завершення. Стіл заблокований.
У MySQL я використовував би їх атомну RENAME TABLEкоманду, щоб уникнути цих проблем ...
CREATE TABLE table_new LIKE table;
INSERT INTO table_new;
RENAME TABLE table TO table_old, table_new TO table; *atomic operation*
DROP TABLE table_old;
Як я міг досягти цього в PostgreSQL?
Для цілей цього питання ви можете припустити, що я не використовую сторонні ключі.
TRUNCATEкоманду придбає AccessExclusive замок на столі, так що ніхто не зможе не читати з таблиці до цієї транзакції або відкат.
deleteзамість truncateнього, буде повільніше, але без блокування читачів. Скільки рядків потрібно видалити?
DELETEі INSERTбув би занадто довгим.