PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Các tùy chọn đa thai cho PostgreSQL

Đa thuê trong một hệ thống phần mềm được gọi là phân tách dữ liệu theo một tập hợp các tiêu chí để đáp ứng một tập hợp các mục tiêu. Mức độ / mở rộng, bản chất và việc thực hiện cuối cùng của sự phân tách này phụ thuộc vào các tiêu chí và mục tiêu đó. Đa thuê nhà về cơ bản là một trường hợp phân vùng dữ liệu nhưng chúng tôi sẽ cố gắng tránh thuật ngữ này vì những lý do rõ ràng (thuật ngữ trong PostgreSQL có một ý nghĩa rất cụ thể và được bảo lưu, như phân vùng bảng khai báo đã được giới thiệu trong postgresql 10).

Các tiêu chí có thể là:

  1. theo id của một bảng chính quan trọng, tượng trưng cho id đối tượng thuê có thể đại diện cho:
    1. một công ty / tổ chức trong một nhóm cổ đông lớn hơn
    2. một bộ phận trong một công ty / tổ chức
    3. văn phòng khu vực / chi nhánh của cùng một công ty / tổ chức
  2. theo vị trí / IP của người dùng
  3. theo vị trí của người dùng trong công ty / tổ chức

Các mục tiêu có thể là:

  1. tách biệt tài nguyên vật lý hoặc tài nguyên ảo
  2. tách biệt các tài nguyên hệ thống
  3. bảo mật
  4. độ chính xác và sự thuận tiện của quản lý / người dùng ở các cấp khác nhau của công ty / tổ chức

Lưu ý rằng bằng cách hoàn thành một mục tiêu, chúng tôi cũng hoàn thành tất cả các mục tiêu bên dưới, tức là bằng cách hoàn thành A, chúng tôi cũng hoàn thành B, C và D, bằng cách hoàn thành B, chúng tôi cũng hoàn thành C và D, v.v.

Nếu chúng ta muốn hoàn thành mục tiêu A, chúng ta có thể chọn triển khai từng đối tượng thuê dưới dạng một cụm cơ sở dữ liệu riêng biệt trong máy chủ vật lý / ảo của chính nó. Điều này giúp tách biệt tối đa tài nguyên và bảo mật nhưng lại cho kết quả kém khi chúng ta cần xem toàn bộ dữ liệu là một, tức là chế độ xem tổng hợp của toàn bộ hệ thống.

Nếu chúng ta chỉ muốn đạt được mục tiêu B, chúng ta có thể triển khai từng đối tượng thuê dưới dạng một cá thể postgresql riêng biệt trong cùng một máy chủ. Điều này sẽ cung cấp cho chúng tôi quyền kiểm soát về lượng không gian sẽ được chỉ định cho mỗi phiên bản và cũng có một số kiểm soát (tùy thuộc vào hệ điều hành) đối với việc sử dụng CPU / mem. Trường hợp này về cơ bản không khác A. Trong thời đại điện toán đám mây hiện đại, khoảng cách giữa A và B có xu hướng ngày càng nhỏ hơn, vì vậy A có lẽ sẽ là cách được ưu tiên hơn B.

Nếu chúng ta muốn đạt được mục tiêu C, tức là bảo mật, thì chỉ cần có một phiên bản cơ sở dữ liệu và triển khai mỗi đối tượng thuê dưới dạng một cơ sở dữ liệu riêng biệt.

Và cuối cùng nếu chúng ta chỉ quan tâm đến việc phân tách dữ liệu “mềm”, hay nói cách khác là các chế độ xem khác nhau của cùng một hệ thống, chúng ta có thể đạt được điều này chỉ bằng một phiên bản cơ sở dữ liệu và một cơ sở dữ liệu, sử dụng rất nhiều kỹ thuật được thảo luận dưới đây là phương pháp cuối cùng (và chính) chủ đề của blog này. Nói về nhiều hình thức cho thuê nhà, theo quan điểm của DBA, các trường hợp A, B và C có rất nhiều điểm tương đồng. Điều này là do trong mọi trường hợp, chúng ta có các cơ sở dữ liệu khác nhau và để kết nối các cơ sở dữ liệu đó, thì các công cụ và công nghệ đặc biệt phải được sử dụng. Tuy nhiên, nếu nhu cầu làm như vậy đến từ bộ phận phân tích hoặc Business Intelligence thì có thể không cần bắc cầu vì dữ liệu có thể được sao chép rất tốt đến một số máy chủ trung tâm dành riêng cho các tác vụ đó, khiến việc bắc cầu không cần thiết. Nếu thực sự cần một cầu nối như vậy thì chúng ta phải sử dụng các công cụ như dblink hoặc bảng ngoại. Bảng ngoại thông qua Trình gói dữ liệu nước ngoài ngày nay là cách ưa thích.

Tuy nhiên, nếu chúng ta sử dụng tùy chọn D, thì hợp nhất đã được đưa ra theo mặc định, vì vậy bây giờ phần khó là ngược lại:tách. Vì vậy, chúng tôi thường phân loại các tùy chọn khác nhau thành hai loại chính:

  • Phân tách nhẹ nhàng
  • Khó phân tách

Phân tách cứng thông qua các cơ sở dữ liệu khác nhau trong cùng một cụm

Giả sử rằng chúng ta phải thiết kế một hệ thống cho một doanh nghiệp tưởng tượng cung cấp dịch vụ cho thuê xe hơi và thuyền, nhưng vì hai công ty đó chịu sự điều chỉnh của các luật khác nhau, các biện pháp kiểm soát, kiểm toán khác nhau, mỗi công ty phải duy trì các bộ phận kế toán riêng biệt và do đó chúng tôi muốn giữ nguyên hệ thống của họ ly thân. Trong trường hợp này, chúng tôi chọn có một cơ sở dữ liệu khác nhau cho mỗi công ty:Rentdb_cars và Rentdb_boats, các cơ sở này sẽ có các lược đồ giống hệt nhau:

# \d customers
                                  Table "public.customers"
   Column    |     Type      | Collation | Nullable |                Default                
-------------+---------------+-----------+----------+---------------------------------------
 id          | integer       |           | not null | nextval('customers_id_seq'::regclass)
 cust_name   | text          |           | not null |
 birth_date  | date          |           |          |
 sex         | character(10) |           |          |
 nationality | text          |           |          |
Indexes:
    "customers_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "rental" CONSTRAINT "rental_customerid_fkey" FOREIGN KEY (customerid) REFERENCES customers(id)
# \d rental
                              Table "public.rental"
   Column   |  Type   | Collation | Nullable |              Default               
------------+---------+-----------+----------+---------------------------------
 id         | integer |           | not null | nextval('rental_id_seq'::regclass)
 customerid | integer |           | not null |
 vehicleno  | text    |           |          |
 datestart  | date    |           | not null |
 dateend    | date    |           |          |
Indexes:
    "rental_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "rental_customerid_fkey" FOREIGN KEY (customerid) REFERENCES customers(id)

Giả sử chúng ta có các dịch vụ cho thuê sau đây. Trong Rentdb_cars:

rentaldb_cars=# select cust.cust_name,rent.vehicleno,rent.datestart FROM rental rent JOIN customers cust on (rent.customerid=cust.id);
    cust_name    | vehicleno | datestart  
-----------------+-----------+------------
 Valentino Rossi | INI 8888  | 2018-08-10
(1 row)

và trong Rentdb_boats:

rentaldb_boats=# select cust.cust_name,rent.vehicleno,rent.datestart FROM rental rent JOIN customers cust on (rent.customerid=cust.id);
   cust_name    | vehicleno | datestart  
----------------+-----------+------------
 Petter Solberg | INI 9999  | 2018-08-10
(1 row)

Bây giờ ban quản lý muốn có một cái nhìn tổng thể về hệ thống, ví dụ:một cách thống nhất để xem giá thuê. Chúng tôi có thể giải quyết vấn đề này thông qua ứng dụng, nhưng nếu chúng tôi không muốn cập nhật ứng dụng hoặc không có quyền truy cập vào mã nguồn, thì chúng tôi có thể giải quyết vấn đề này bằng cách tạo cơ sở dữ liệu trung tâm Rentdb và bằng cách sử dụng các bảng ngoại, như sau:

CREATE EXTENSION IF NOT EXISTS postgres_fdw WITH SCHEMA public;
CREATE SERVER rentaldb_boats_srv FOREIGN DATA WRAPPER postgres_fdw OPTIONS (
    dbname 'rentaldb_boats'
);
CREATE USER MAPPING FOR postgres SERVER rentaldb_boats_srv;
CREATE SERVER rentaldb_cars_srv FOREIGN DATA WRAPPER postgres_fdw OPTIONS (
    dbname 'rentaldb_cars'
);
CREATE USER MAPPING FOR postgres SERVER rentaldb_cars_srv;
CREATE FOREIGN TABLE public.customers_boats (
    id integer NOT NULL,
    cust_name text NOT NULL
)
SERVER rentaldb_boats_srv
OPTIONS (
    table_name 'customers'
);
CREATE FOREIGN TABLE public.customers_cars (
    id integer NOT NULL,
    cust_name text NOT NULL
)
SERVER rentaldb_cars_srv
OPTIONS (
    table_name 'customers'
);
CREATE VIEW public.customers AS
 SELECT 'cars'::character varying(50) AS tenant_db,
    customers_cars.id,
    customers_cars.cust_name
   FROM public.customers_cars
UNION
 SELECT 'boats'::character varying AS tenant_db,
    customers_boats.id,
    customers_boats.cust_name
   FROM public.customers_boats;
CREATE FOREIGN TABLE public.rental_boats (
    id integer NOT NULL,
    customerid integer NOT NULL,
    vehicleno text NOT NULL,
    datestart date NOT NULL
)
SERVER rentaldb_boats_srv
OPTIONS (
    table_name 'rental'
);
CREATE FOREIGN TABLE public.rental_cars (
    id integer NOT NULL,
    customerid integer NOT NULL,
    vehicleno text NOT NULL,
    datestart date NOT NULL
)
SERVER rentaldb_cars_srv
OPTIONS (
    table_name 'rental'
);
CREATE VIEW public.rental AS
 SELECT 'cars'::character varying(50) AS tenant_db,
    rental_cars.id,
    rental_cars.customerid,
    rental_cars.vehicleno,
    rental_cars.datestart
   FROM public.rental_cars
UNION
 SELECT 'boats'::character varying AS tenant_db,
    rental_boats.id,
    rental_boats.customerid,
    rental_boats.vehicleno,
    rental_boats.datestart
   FROM public.rental_boats;

Để xem tất cả các khoản cho thuê và khách hàng trong toàn bộ tổ chức, chúng tôi chỉ cần thực hiện:

rentaldb=# select cust.cust_name, rent.* FROM rental rent JOIN customers cust ON (rent.tenant_db=cust.tenant_db AND rent.customerid=cust.id);
    cust_name    | tenant_db | id | customerid | vehicleno | datestart  
-----------------+-----------+----+------------+-----------+------------
 Petter Solberg  | boats     |  1 |          1 | INI 9999  | 2018-08-10
 Valentino Rossi | cars      |  1 |          2 | INI 8888  | 2018-08-10
(2 rows)

Điều này có vẻ ổn, sự cô lập và bảo mật được đảm bảo, sự hợp nhất đã đạt được, nhưng vẫn còn tồn tại những vấn đề:

  • khách hàng phải được duy trì riêng biệt, nghĩa là cùng một khách hàng có thể có hai tài khoản
  • Ứng dụng phải tôn trọng khái niệm về một cột đặc biệt (chẳng hạn như tenant_db) và thêm cột này vào mọi truy vấn, khiến nó dễ bị lỗi
  • Các chế độ xem kết quả không được cập nhật tự động (vì chúng chứa UNION)

Phân tách mềm trong cùng một cơ sở dữ liệu

Khi cách tiếp cận này được chọn thì sự hợp nhất được đưa ra khỏi hộp và bây giờ phần khó khăn là sự tách biệt. PostgreSQL cung cấp rất nhiều giải pháp cho chúng tôi để thực hiện phân tách:

  • Lượt xem
  • Bảo mật cấp độ vai trò
  • Lược đồ

Với các dạng xem, ứng dụng phải đặt một cài đặt có thể truy vấn, chẳng hạn như application_name, chúng tôi ẩn bảng chính sau một dạng xem, sau đó trong mọi truy vấn trên bất kỳ bảng con nào (như trong phụ thuộc FK), nếu có, của bảng chính này kết hợp với quan điểm này. Chúng ta sẽ thấy điều này trong ví dụ sau trong cơ sở dữ liệu mà chúng ta gọi là Rentdb_one. Chúng tôi nhúng thông tin nhận dạng công ty của người thuê vào bảng chính:

rentaldb_one=# \d rental_one
                                   Table "public.rental_one"
   Column   |         Type          | Collation | Nullable |              Default               
------------+-----------------------+-----------+----------+------------------------------------
 company    | character varying(50) |           | not null |
 id         | integer               |           | not null | nextval('rental_id_seq'::regclass)
 customerid | integer               |           | not null |
 vehicleno  | text                  |           |          |
 datestart  | date                  |           | not null |
 dateend    | date                  |           |          |
Indexes:
    "rental_pkey" PRIMARY KEY, btree (id)
Check constraints:
    "rental_company_check" CHECK (company::text = ANY (ARRAY['cars'::character varying, 'boats'::character varying]::text[]))
Foreign-key constraints:
    "rental_customerid_fkey" FOREIGN KEY (customerid) REFERENCES customers(id)
Tải xuống Báo cáo chính thức hôm nay Quản lý &Tự động hóa PostgreSQL với ClusterControlTìm hiểu về những điều bạn cần biết để triển khai, giám sát, quản lý và mở rộng PostgreSQLTải xuống Báo cáo chính thức

Lược đồ của khách hàng trong bảng vẫn giữ nguyên. Cho phép xem nội dung hiện tại của cơ sở dữ liệu:

rentaldb_one=# select * from customers;
 id |    cust_name    | birth_date | sex | nationality
----+-----------------+------------+-----+-------------
  2 | Valentino Rossi | 1979-02-16 |     |
  1 | Petter Solberg  | 1974-11-18 |     |
(2 rows)
rentaldb_one=# select * from rental_one ;
 company | id | customerid | vehicleno | datestart  | dateend
---------+----+------------+-----------+------------+---------
 cars    |  1 |          2 | INI 8888  | 2018-08-10 |
 boats   |  2 |          1 | INI 9999  | 2018-08-10 |
(2 rows)

Chúng tôi sử dụng tên mới Rent_one để ẩn điều này đằng sau chế độ xem mới sẽ có cùng tên bảng mà ứng dụng mong đợi:cho thuê. Ứng dụng sẽ cần đặt tên ứng dụng để biểu thị người thuê. Vì vậy, trong ví dụ này, chúng ta sẽ có ba phiên bản của ứng dụng, một cho ô tô, một cho tàu thuyền và một cho quản lý cao nhất. Tên ứng dụng được đặt như sau:

rentaldb_one=# set application_name to 'cars';

Bây giờ chúng tôi tạo chế độ xem:

create or replace view rental as select company as "tenant_db",id,customerid,vehicleno,datestart,dateend from rental_one where (company = current_setting('application_name') OR current_setting('application_name')='all');

Lưu ý:Chúng tôi giữ nguyên các cột và tên bảng / chế độ xem giống nhau, điểm quan trọng trong các giải pháp cho nhiều đối tượng thuê là giữ cho mọi thứ giống nhau ở phía ứng dụng và các thay đổi ở mức tối thiểu và có thể quản lý được.

Hãy thực hiện một số lựa chọn:

Rentdb_one =# đặt application_name thành 'ô tô';

rentaldb_one=# set application_name to 'cars';
SET
rentaldb_one=# select * from rental;
 tenant_db | id | customerid | vehicleno | datestart  | dateend
-----------+----+------------+-----------+------------+---------
 cars      |  1 |          2 | INI 8888  | 2018-08-10 |
(1 row)
rentaldb_one=# set application_name to 'boats';
SET
rentaldb_one=# select * from rental;
 tenant_db | id | customerid | vehicleno | datestart  | dateend
-----------+----+------------+-----------+------------+---------
 boats     |  2 |          1 | INI 9999  | 2018-08-10 |
(1 row)
rentaldb_one=# set application_name to 'all';
SET
rentaldb_one=# select * from rental;
 tenant_db | id | customerid | vehicleno | datestart  | dateend
-----------+----+------------+-----------+------------+---------
 cars      |  1 |          2 | INI 8888  | 2018-08-10 |
 boats     |  2 |          1 | INI 9999  | 2018-08-10 |
(2 rows)

Phiên bản thứ 3 của ứng dụng phải đặt tên ứng dụng thành “tất cả” nhằm mục đích sử dụng bởi cấp quản lý cao nhất với chế độ xem toàn bộ cơ sở dữ liệu.

Một giải pháp mạnh mẽ hơn, về mặt bảo mật, có thể dựa trên RLS (bảo mật mức hàng). Trước tiên, chúng tôi khôi phục tên của bảng, hãy nhớ rằng chúng tôi không muốn làm phiền ứng dụng:

rentaldb_one=# alter view rental rename to rental_view;
rentaldb_one=# alter table rental_one rename TO rental;

Đầu tiên, chúng tôi tạo hai nhóm người dùng cho mỗi công ty (tàu thuyền, ô tô), nhóm này phải xem tập hợp con dữ liệu của riêng họ:

rentaldb_one=# create role cars_employees;
rentaldb_one=# create role boats_employees;

Bây giờ chúng tôi tạo các chính sách bảo mật cho từng nhóm:

rentaldb_one=# create policy boats_plcy ON rental to boats_employees USING(company='boats');
rentaldb_one=# create policy cars_plcy ON rental to cars_employees USING(company='cars');

Sau khi trao các khoản trợ cấp cần thiết cho hai vai trò:

rentaldb_one=# grant ALL on SCHEMA public to boats_employees ;
rentaldb_one=# grant ALL on SCHEMA public to cars_employees ;
rentaldb_one=# grant ALL on ALL tables in schema public TO cars_employees ;
rentaldb_one=# grant ALL on ALL tables in schema public TO boats_employees ;

chúng tôi tạo một người dùng cho mỗi vai trò

rentaldb_one=# create user boats_user password 'boats_user' IN ROLE boats_employees;
rentaldb_one=# create user cars_user password 'cars_user' IN ROLE cars_employees;

Và kiểm tra:

[email protected]:~> psql -U cars_user rentaldb_one
Password for user cars_user:
psql (10.5)
Type "help" for help.

rentaldb_one=> select * from rental;
 company | id | customerid | vehicleno | datestart  | dateend
---------+----+------------+-----------+------------+---------
 cars    |  1 |          2 | INI 8888  | 2018-08-10 |
(1 row)

rentaldb_one=> \q
[email protected]:~> psql -U boats_user rentaldb_one
Password for user boats_user:
psql (10.5)
Type "help" for help.

rentaldb_one=> select * from rental;
 company | id | customerid | vehicleno | datestart  | dateend
---------+----+------------+-----------+------------+---------
 boats   |  2 |          1 | INI 9999  | 2018-08-10 |
(1 row)

rentaldb_one=>

Điều thú vị với cách tiếp cận này là chúng tôi không cần nhiều phiên bản của ứng dụng. Tất cả sự cô lập được thực hiện ở cấp cơ sở dữ liệu dựa trên vai trò của người dùng. Do đó, để tạo người dùng trong quyền quản lý cao nhất, tất cả những gì chúng ta cần làm là cấp cho người dùng này cả hai vai trò:

rentaldb_one=# create user all_user password 'all_user' IN ROLE boats_employees, cars_employees;
[email protected]:~> psql -U all_user rentaldb_one
Password for user all_user:
psql (10.5)
Type "help" for help.

rentaldb_one=> select * from rental;
 company | id | customerid | vehicleno | datestart  | dateend
---------+----+------------+-----------+------------+---------
 cars    |  1 |          2 | INI 8888  | 2018-08-10 |
 boats   |  2 |          1 | INI 9999  | 2018-08-10 |
(2 rows)

Nhìn vào hai giải pháp đó, chúng tôi thấy rằng giải pháp chế độ xem yêu cầu thay đổi tên bảng cơ bản, điều này có thể khá xâm phạm ở chỗ chúng tôi có thể cần chạy chính xác cùng một lược đồ trong một giải pháp không có nhiều đối tượng hoặc với một ứng dụng không biết application_name , trong khi giải pháp thứ hai ràng buộc mọi người với những người thuê cụ thể. Điều gì sẽ xảy ra nếu cùng một người làm việc v.d. trên những chiếc thuyền cho thuê vào buổi sáng và trên những chiếc xe cho thuê vào buổi chiều? Chúng ta sẽ thấy một giải pháp thứ ba dựa trên các lược đồ, theo ý kiến ​​của tôi là linh hoạt nhất và không mắc phải bất kỳ cảnh báo nào trong số hai giải pháp được mô tả ở trên. Nó cho phép ứng dụng chạy theo cách bất khả tri đối với người thuê và các kỹ sư hệ thống có thể thêm người thuê khi đang di chuyển khi có nhu cầu. Chúng tôi sẽ giữ nguyên thiết kế như trước, với cùng một dữ liệu thử nghiệm (chúng tôi sẽ tiếp tục làm việc trên db ví dụ Rentdb_one). Ý tưởng ở đây là thêm một lớp ở phía trước bảng chính dưới dạng một đối tượng cơ sở dữ liệu trong một giản đồ riêng biệt sẽ đủ sớm trong search_path cho người thuê cụ thể đó. Đường dẫn tìm kiếm có thể được đặt (lý tưởng là thông qua một chức năng đặc biệt, cung cấp nhiều tùy chọn hơn) trong cấu hình kết nối của nguồn dữ liệu tại lớp máy chủ ứng dụng (do đó nằm ngoài mã ứng dụng). Đầu tiên, chúng tôi tạo hai lược đồ:

rentaldb_one=# create schema cars;
rentaldb_one=# create schema boats;

Sau đó, chúng tôi tạo các đối tượng cơ sở dữ liệu (dạng xem) trong mỗi lược đồ:

CREATE OR REPLACE VIEW boats.rental AS
 SELECT rental.company,
    rental.id,
    rental.customerid,
    rental.vehicleno,
    rental.datestart,
    rental.dateend
   FROM public.rental
  WHERE rental.company::text = 'boats';
CREATE OR REPLACE VIEW cars.rental AS
 SELECT rental.company,
    rental.id,
    rental.customerid,
    rental.vehicleno,
    rental.datestart,
    rental.dateend
   FROM public.rental
  WHERE rental.company::text = 'cars';

Bước tiếp theo là đặt đường dẫn tìm kiếm trong từng đối tượng thuê như sau:

  • Đối với người thuê thuyền:

    set search_path TO 'boats, "$user", public';
  • Đối với người thuê ô tô:

    set search_path TO 'cars, "$user", public';
  • Đối với người thuê mgmt hàng đầu, hãy để nó ở chế độ mặc định

Hãy kiểm tra:

rentaldb_one=# select * from rental;
 company | id | customerid | vehicleno | datestart  | dateend
---------+----+------------+-----------+------------+---------
 cars    |  1 |          2 | INI 8888  | 2018-08-10 |
 boats   |  2 |          1 | INI 9999  | 2018-08-10 |
(2 rows)

rentaldb_one=# set search_path TO 'boats, "$user", public';
SET
rentaldb_one=# select * from rental;
 company | id | customerid | vehicleno | datestart  | dateend
---------+----+------------+-----------+------------+---------
 boats   |  2 |          1 | INI 9999  | 2018-08-10 |
(1 row)

rentaldb_one=# set search_path TO 'cars, "$user", public';
SET
rentaldb_one=# select * from rental;
 company | id | customerid | vehicleno | datestart  | dateend
---------+----+------------+-----------+------------+---------
 cars    |  1 |          2 | INI 8888  | 2018-08-10 |
(1 row)
Tài nguyên liên quan ClusterControl for PostgreSQL PostgreSQL Trigger và Stored Chức năng Cơ bản Điều chỉnh Hoạt động Đầu vào / Đầu ra (I / O) cho PostgreSQL

Thay vì đặt search_path, chúng tôi có thể viết một hàm phức tạp hơn để xử lý logic phức tạp hơn và gọi hàm này trong cấu hình kết nối của ứng dụng hoặc trình gộp kết nối của chúng tôi.

Trong ví dụ trên, chúng tôi đã sử dụng cùng một bảng trung tâm nằm trên lược đồ công khai (public.rental) và hai chế độ xem bổ sung cho mỗi đối tượng thuê, sử dụng thực tế may mắn là hai chế độ xem đó đơn giản và do đó có thể ghi được. Thay vì các khung nhìn, chúng tôi có thể sử dụng kế thừa, bằng cách tạo một bảng con cho mỗi đối tượng thuê kế thừa từ bảng công khai. Đây là một kết hợp tốt cho việc kế thừa bảng, một tính năng độc đáo của PostgreSQL. Bảng trên cùng có thể được định cấu hình với các quy tắc để không cho phép chèn. Trong giải pháp kế thừa, một chuyển đổi sẽ cần thiết để điền các bảng con và ngăn chặn quyền truy cập chèn vào bảng mẹ, vì vậy điều này không đơn giản như trong trường hợp với các khung nhìn, hoạt động với tác động tối thiểu đến thiết kế. Chúng tôi có thể viết một blog đặc biệt về cách làm điều đó.

Ba phương pháp trên có thể được kết hợp để đưa ra nhiều lựa chọn hơn nữa.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Chuyển đổi một ngày Julian thành một ngày trong PostgreSQL

  2. Cách cấp tất cả các đặc quyền về chế độ xem cho người dùng tùy ý

  3. Django:Nhóm truy vấn theo tháng

  4. Cân bằng tải PostgreSQL trong đám mây trở nên dễ dàng

  5. Không thể cài đặt PostgreSQL:Đã xảy ra lỗi khi thực thi trình cài đặt thời gian chạy Microsoft VC ++ trên Windows XP