Làm cách nào để ngăn chặn các thay đổi đối với cơ sở dữ liệu PostgreQuery của tôi?


8

Các bước của tôi:

  1. chạy trận chung kết pg_dumpalltrên máy chủprod-server-old
  2. Tắt máy prod-server-oldmãi mãi.
  3. sao chép đầu ra sang một máy chủ khác ( prod-server-new)
  4. Khôi phục db ở đó.
  5. Tất cả lưu lượng truy cập đến prod-server-newbây giờ

Làm cách nào tôi có thể tránh sửa đổi cơ sở dữ liệu trong pg_dumpall(giữa bước 1 và bước 2), để sửa đổi trong thời gian này không thể bị mất?

Trong trường hợp của tôi, nó là 100% OK để có một thời gian xuống nhỏ.

Có một số cơ sở dữ liệu trong "cụm" (btw, tôi không thích từ "cụm". Tôi đoán hầu hết mọi người nghĩ rằng "cụm" là một nhóm của một số máy tính, nhưng trong trường hợp này có nghĩa là một máy chủ Postgres, chứa một số cơ sở dữ liệu).

Câu hỏi của tôi được đánh dấu là có thể trùng lặp với "Tạo cơ sở dữ liệu Postgres chỉ đọc tạm thời (để thực hiện ảnh chụp nhanh khối lượng)". Tôi không nghĩ đó là một bản sao, vì trong trường hợp của tôi thì khác vì tôi không yêu cầu trạng thái chỉ đọc tạm thời.



Bạn có thể thử nhân rộng hợp lý . cơ sở dữ liệu nguồn có thể tiếp tục ghi cho đến khi bạn chuyển đổi.
Sahap Asci

Câu trả lời:


3

Hai cách để làm điều đó:

  • Nếu bạn không bận tâm về thời gian chết (cách dễ dàng):

thu hồi connectđặc quyền cho publicnhóm. Điều đó sẽ ngăn tất cả mọi người trừ các siêu nhân kết nối. Sau đó khởi động lại máy chủ hoặc chấm dứt tất cả các kết nối , sau đó tiến hành sao lưu bằng tài khoản superuser.

REVOKE CONNECT TO DATABASE (database) FROM public
  • Nếu bạn bận tâm về thời gian chết:

Đặt cơ sở dữ liệu của bạn ở chế độ chỉ đọc:

ALTER DATABASE (database) SET default_transaction_read_only = true;

Tiến hành với pg_dumpall. Không cần khởi động lại và không có thời gian chết.

Tất nhiên, bạn phải lặp lại điều này trên mọi cơ sở dữ liệu mà bạn muốn "khóa". Nếu bạn có số lượng cơ sở dữ liệu đáng kể, bạn có thể đặt toàn bộ cụm chỉ đọc: đặt default_transaction_read_only = on;trong postgresql.conf sau đó tải lại dịch vụ postgres.

Xin lưu ý rằng tôi đã không kiểm tra bất kỳ lệnh nào trong số này, hãy tự chịu rủi ro.


Lưu ý rằng các giao dịch chỉ đọc chỉ là một mặc định . Một ứng dụng có thể chỉ cần yêu cầu giao dịch đọc / ghi. Hãy chắc chắn rằng ứng dụng của bạn sẽ không làm điều đó.
Craig Ringer

Tôi nghĩ về điều này một lần nữa. Có pg_dumpall đổ trạng thái chỉ đọc này? Điều này sẽ khiến tôi cần thiết lập lại cơ sở dữ liệu ở chế độ ghi sau khi tôi khôi phục kết xuất prod-server-new. Hoặc làm các cài đặt ở trên không bị đổ bởi pg_dumpall?
guettli

2

Một cách giải quyết:

Thay đổi cổng của PostgreSQL trên prod-server-old. Bằng cách này, không chắc là máy khách kết nối với DB trong khi pg_dumpall --port=OTHER_PORT.


2

Tôi là quản trị viên SQL Server (không phải Postgres) nên tôi không chắc chắn 100%, nhưng nếu thời gian chết không phải là vấn đề bạn có thể:

  • giết tất cả các kết nối
  • ngăn chặn đăng nhập từ xa
  • đăng nhập vào máy chủ db và đăng nhập vào db với tư cách là siêu người dùng
  • làm pg_dumpall
  • kích hoạt lại đăng nhập từ xa

?


Vui lòng giải thích "ngăn chặn đăng nhập từ xa"
guettli

0

Sử dụng kích hoạt:

create function __fn_db_readonly() returns event_trigger language plpgsql as $$
begin
  raise exception '%', 'Database is in read-only mode';
end $$;

create function _fn_db_readonly() returns trigger language plpgsql as $$
begin
  raise exception '%', TG_ARGV[0];
end $$;

create function set_db_readonly(amessage text) returns void language plpgsql as $$
declare
  t record;
  tbl_name text;
  stm text;
begin
  if coalesce(amessage, '') = '' then
    -- Database
    drop event trigger __tg_ro_database1;
    drop event trigger __tg_ro_database2;
    drop event trigger __tg_ro_database3;
    -- Data
    for t in (select * from pg_tables where not schemaname in ('pg_catalog', 'information_schema')) loop
      tbl_name := format('%I.%I', t.schemaname, t.tablename);
      stm := 'drop trigger if exists _tg_ro on ' || tbl_name;
      execute stm;
    end loop;
  else
    -- Data
    for t in (select * from pg_tables where not schemaname in ('pg_catalog', 'information_schema')) loop
      tbl_name := format('%I.%I', t.schemaname, t.tablename);
      stm := format('create trigger _tg_ro before insert or update or delete on %s execute procedure _fn_db_readonly(%L)', tbl_name, amessage);
      execute stm;
    end loop;
    -- Database
    create event trigger __tg_ro_database1 on ddl_command_start execute procedure __fn_db_readonly();
    create event trigger __tg_ro_database2 on table_rewrite execute procedure __fn_db_readonly();
    create event trigger __tg_ro_database3 on sql_drop execute procedure __fn_db_readonly();
  end if;
  return;
end $$;

Sau đó, để làm cho cơ sở dữ liệu chỉ đọc:

select set_db_readonly('Database is in read-only mode due to maintance.');

và để làm cho nó có thể chỉnh sửa một lần nữa:

select set_db_readonly('');
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.