2014-01-17 2 views
3

문제점이 있으며 지금까지 단서를 찾지 못했습니다. 내가 할 수있는 최선의 방법을 설명하려고 노력할 것이지만, 더 자세한 내용을 자유롭게 묻자!사용자가 기본 테이블 스페이스에 테이블을 생성하지 못하도록합니다.

상황

내가 Windows에서 포스트 그레스 9.2.4 함께 일하고 있어요, 나는 각 사용자에 대한 할당량 관리의 어떤 종류를 구현해야합니다.

필자가 읽은만큼 기본 제공되는 기능은 없으며 대부분의 답변은 파일 시스템의 할당량 관리 기능을 사용한다는 점을 지적합니다.

하나의 데이터베이스가 있으며 각 사용자는 자신의 스키마를 갖습니다.

내가 취한 접근법은 각 사용자마다 테이블 스페이스가 다른 테이블 스페이스를 사용함으로써 각기 다른 위치에있는 각 사용자의 데이터 파일을 분리하는 것입니다 (사용자가 자신의 테이블 스페이스 소유자이기 때문에 폴더 단위 기준).

이 내가 직면하고있어 문제를 알려준 ...

문제

테이블을 생성 할 때, 사용자가 저장하는 pg_default에게 테이블을 선택 할 수 있다는 발생 자료.

나중에 사용자가 소유 한 테이블 스페이스로 변경 한 다음 pg_default 테이블 스페이스로 다시 전환하려고하면 권한 거부 오류가 발생합니다.

-- Creates the table in the default tablespace 
CREATE TABLE test_schema.test_table () 
TABLESPACE pg_default; 

-- Changes the tablespace to the one owned by the user 
ALTER TABLE test_schema.test_table 
SET TABLESPACE user_tablespace; 

-- Tries to set back the pg_default tablespace (throws permission denied to pg_default tablespace) 
ALTER TABLE test_schema.test_table 
SET TABLESPACE pg_default; 

이 모든 명령은 관리자 권한이없는 사용자 로그인을 사용하여 수행되었다 : 여기 순서를 명확히하기 위해

은 몇 가지 예제 코드입니다. pg_default 테이블 스페이스는 postgres 로그인 (관리 계정)이 소유합니다.

내 생각 엔 pg_default 테이블 스페이스를 사용하도록 설정된 데이터베이스 테이블 스페이스와 관련이 있다고 생각합니다.

자신의 소유 테이블 만 생성 객체에 사용자를 제약 조건 할 수

질문?

+1

'pg_default'로 돌아가는 문제는 버그입니다. 수정 사항이 방금 제안되었습니다 - http://www.postgresql.org/message-id/[email protected] –

+0

@CraigRinger가 그것을 지적 해 주셔서 고마워요, 우연의 일치! 필자가 이해 하듯이 사용자는 소유권에 관계없이 _database_ tablespace를 사용할 수있는 권한을 항상 가지게됩니다. – Chopin

답변

2

디스크 할당량을 사용하면 엄청난 양의 작업을 할 수 있습니다. 사실, PostgreSQL에는 대략적인 해결책이 있습니다. 약간의 땜질과 많은 수의 테이블 공간을 만들 필요가 없습니다 (스키마는 모든 사용자에게 자신의 네임 스페이스를 제공하는 데 여전히 좋은 아이디어입니다).

함수 pg_total_relation_size(regclass)은 색인 및 TOAST 테이블을 포함하여 테이블에 사용 된 전체 디스크 공간을 제공합니다. 그래서 pg_class를 스캔하고 요약 :이 관계없이 테이블의 위치, 당신에게 각 소유자에 의해 사용되는 전체 디스크 공간을 제공

CREATE VIEW user_disk_usage AS 
    SELECT r.rolname, SUM(pg_total_relation_size(c.oid)) AS total_disk_usage 
    FROM pg_class c, pg_roles r 
    WHERE c.relkind = 'r' 
    AND c.relowner = r.oid 
    GROUP BY c.relowner; 

. 아래에서 사용하기 위해 뷰 정의로 제시됩니다.

합리적으로 정확한 방식으로 작동 시키려면 데이터베이스를 정기적으로 VACUUM ANALYZE해야합니다.소통량이 적은 경우 (예 : 매일 오전 3 시부 터 오전 5 시까 지 또는 일요일), 사용자 포스트그레스로 예약 된 작업을 사용하여 실행하십시오. 소유자가 모든 관련 스키마에 REVOKE CREATE 수있는 할당량, 일반적으로 단지 사용자에게 할당 된 스키마와 공공 스키마를 통해가는 경우

CREATE FUNCTION user_quota_check() RETURNS void AS $$ 
DECLARE 
    user_data record; 
BEGIN 
    -- Vacuum the database to get accurate disk use data 
    VACUUM FULL ANALYZE; 

    -- Find users over disk quota 
    FOR user_data IN SELECT * FROM user_disk_usage LOOP 
    IF (user_data.total_disk_usage > <<your quota>>) THEN 
     EXECUTE 'REVOKE CREATE ON SCHEMA ' || <<user''s schema name>> || ', PUBLIC FROM ' || user_data.rolname; 
     -- REVOKE INSERT privileges too, unless you work with BEFORE INSERT triggers on all tables 
    END IF; 
    END LOOP; 
END; $$ LANGUAGE plpgsql; 
REVOKE ALL ON FUNCTION user_quota_check() FROM PUBLIC; 

: 진공하고 할당량 검사를 수행하는 작업에 대한 함수를 만듭니다 , 새로운 테이블을 작성할 수 없게됩니다. 모든 테이블에 REVOKE INSERT도 있어야하지만 소유자가 GRANT INSERT 바로 뒤에 있기 때문에 쉽게 피할 수 있습니다. 그러나 이는 사용자에 대해보다 과감한 조치를 취할 수 있습니다. 데이터베이스의 모든 테이블에 이전 삽입 트리거를 작성하고 위의 것과 같은 일일 스윕을 사용하는 것이 바람직합니다.

사용자는 여전히 데이터에 액세스 할 수 있도록 SELECT 권한이 있습니다. 더 흥미롭게도, DELETE와 TRUNCATE는 사용자가 디스크 공간을 비우고 잠금을 해결할 수있게합니다.

CREATE FUNCTION reclaim_disk_space() RETURNS void AS $$ 
DECLARE 
    disk_use bigint; 
BEGIN 
    -- Vacuum current_user's tables. 
    -- Slow and therefore adequate punishment for going over quota. 
    VACUUM FULL VERBOSE ANALYZE; 

    -- Now re-instate privileges if enough space was reclaimed. 
    SELECT total_disk_usage INTO disk_use 
    FROM user_disk_usage 
    WHERE rolname = session_user; 
    IF (disk_use < <<your quota>>) THEN 
    EXECUTE 'GRANT CREATE ON SCHEMA ' || <<user''s schema name>> || ', PUBLIC TO ' || user_data.rolname; 
    -- GRANT INSERT privileges too, unless you work with BEFORE INSERT triggers on all tables 
    RAISE NOTICE 'Disk use under quota limit. Privileges restored.'; 
    ELSE 
    RAISE NOTICE 'Still using too much disk space. Free up more space.'; 
    END IF; 
END; $$ LANGUAGE plpgsql;  

잠긴 아웃 사용자가 할당량 제한에 따라 갈 수있는 충분한 데이터를 삭제 한 후이 기능 그를 -/자신 호출 할 수 있습니다 : 특권은 다음 위의 함수와 유사한 것을 사용 복직 할 수 있습니다.

할당량의 80 %를 넘을 때 삽입 트리거에 RAISE NOTICE을 발행하고 (전체 할당량 대신) 사용자 당 할당량을 나열하는 테이블을 갖는 것과 같은 더 복잡한 기능을 추가 할 수 있습니다. 이것은 모든 테이블에 이전 테이블 삽입 트리거가 있어야합니다.이 테이블은 postgres 사용자가 새 테이블을 정기적으로 스윕 할 때 쉽게 수행 할 수 있습니다. 동일한 트리거를 사용하여 할당량을 초과하면 삽입을 거부 할 수 있습니다. 마지막 알림이 발령되었을 때 등)

이 해결 방법은 할당량이 실시간으로 확인되지 않기 때문에 대략적인 해결책입니다. 이것은 가능합니다 (모든 삽입에서 user_quota_check()을 실행하고 session_user의 테이블 만 확인하도록 수정되었지만 흥미를 유발하기에 너무 많은 오버 헤드가있을 수 있습니다). 매일 quotas를 관리하려면 user_quota_check()를 밤새 실행하십시오. 그리고 하루 종일 너무 많은 공간을 사용하여 사용자를 괴롭 히십시오.

+0

그런 상세한 답변을 보내 주셔서 감사합니다. 나는 당신이 묘사 한 것과 매우 유사한 전략으로 끝내었다. (내 구체적인 상황에 기초한 미묘한 차이점을 가지고), 사전 대책보다는 반응 적 접근 (주기적으로 점검을 수행하고 더 많은 삽입을 막기 위해 작업 스케줄링)을 사용했다. 사용자가 할당량을 초과하는 경우). 나는 '진공 (Vacuum)'수술을 고려하지 않았으므로, 그것을 개정 할 것입니다. 내가 원래의 질문을 직접 다루지는 않았지만, 당신의 대답을 받아 들였다. 왜냐하면 그것이 그 뒤에있는 시나리오를 아주 잘 풀기 때문이다. 다시 한 번 감사드립니다! – Chopin

관련 문제