2009-05-29 6 views
5

우리는 Postgres에 스키마가 있으며, 스키마 패치를 적용하기위한 좋은 방법을 찾고 싶습니다.스키마 패치 연습

현재 스키마, 테이블, 시퀀스, 함수 등을 생성하는 일련의 DDL 파일이 있습니다. 테스트 환경을위한 채우기 (population) 스크립트도 있습니다. 이 파일들은 모두 개발, 테스트 등을 위해 데이터베이스 환경을 재현하는 데 사용됩니다.

또한 우리 시스템의 버전에 해당하는 많은 '패치'파일이 있습니다. 즉. patches/1.0.0.sql, patches/1.0.1.sql 등이 있습니다.이 파일은 준비 및 프로덕션 데이터베이스를 업데이트하는 데 사용됩니다.

이 프로세스는 지금까지 우리에게 효과적 이었지만 스키마를 가장 잘 패치하는 방법에 대한 사내 토론이있었습니다.

다른 사람들이 준비 및 프로덕션 스키마를 패치하고 데이터베이스 버전을 관리하는 방법에 대해 궁금합니다.

감사합니다.

답변

3

직장에서 SQL Server의 경우 스키마 변경 스크립트를 작성하여 변경 사항을 먼저 롤백하고 (idempotently, 스키마 변경이 아직 적용되지 않은 경우에도 롤백 섹션이 잘 실행되도록) 변경 사항을 적용합니다. TSQL에서는 테이블/열/인덱스/행이 이미 있는지 확인하고 그렇지 않은 경우 아무 작업도 수행하지 않아도 시스템 카탈로그 나 다른 테이블을 쉽게 들여다 볼 수 있습니다.

PostgreSQL에서는 단순히 서버에 보낼 수있는 명령이 조금 더 제한되어 있지만 DDL은 트랜잭션 방식이므로 절반으로 적용된 스키마 변경은 발생하지 않아야합니다. 나는 직장에서 익숙한 계획을 아주 작은 프로젝트에서 사용하기에 적합했다. (과장은 없지만 심지어 여기에는 dev/test db와 "실제"db가있다.)

\echo Rolling back schema change #35 

BEGIN; 

DELETE FROM schema_version WHERE schema_id = 35; 

DROP TABLE IF EXISTS location_coordinates; 
DROP FUNCTION IF EXISTS location_coordinates_populate(); 

END; 

\echo Applying schema change #35 

BEGIN; 

INSERT INTO schema_version(schema_id, description) VALUES(35, 'Add location_coordinates table'); 

CREATE TABLE location_coordinates(
location_id INT PRIMARY KEY REFERENCES location(location_id), 
latitude FLOAT NOT NULL, 
longitude FLOAT NOT NULL, 
earth_coordinates earth NOT NULL, 
box_10miles cube NOT NULL 
); 

GRANT SELECT, INSERT, UPDATE, DELETE ON location_coordinates TO ui; 

CREATE FUNCTION location_coordinates_populate() RETURNS TRIGGER LANGUAGE 'plpgsql' AS $$ 
BEGIN 
    new.earth_coordinates := ll_to_earth(new.latitude, new.longitude); 
    new.box_10miles := earth_box(new.earth_coordinates, 10 * 1609.344); 
    RETURN new; 
END 
$$; 

CREATE TRIGGER location_coordinates_populate BEFORE INSERT OR UPDATE ON location_coordinates 
FOR EACH ROW EXECUTE PROCEDURE location_coordinates_populate(); 

INSERT INTO location_coordinates(location_id, latitude, longitude) 
SELECT location_id, latitude, longitude FROM location WHERE latitude IS NOT NULL AND longitude IS NOT NULL; 

CREATE INDEX location_coordinates_10miles ON location_coordinates USING gist (box_10miles); 

END; 

\echo Done 

이 스크립트는 "psql -f schema-changes/35.sql"을 사용하여 데이터베이스에서 실행할 수 있습니다. "적용 중 ..."메시지를 잘라내어 다시 롤백하라는 명령을받을 수 있습니다. 보시다시피 변경 사항은 메타 데이터 테이블 "schema_version"을 유지하므로 어떤 변경 사항이 적용되는지 확인할 수 있습니다. 전체 변경은 트랜잭션, 데이터 마이그레이션 및 전체로 수행됩니다. 여기에서는 DROP 명령의 "IF EXISTS"기능을 사용하여 변경 사항이 적용되지 않은 경우에도 롤백 섹션을 행복하게 만듭니다. 우리가 Oracle에서 일한 Istr은 PL/SQL로 스키마 변경을 작성했습니다. plpgsql에서 변경을 돕기 위해 일부 기능을 사용할 수 있습니까?

위의 변경에서 "위치"에서 "위도"및 "경도"열 (nullable)을 별도의 "location_coordinates"관계로 이전한다는 점에 유의하십시오 (그리고 지구 궤도에 추가) , 나는 오래된 칼럼을 떨어 뜨리지 않았다. 우리가 조심해야 할 한 가지는 가능한 경우 스키마 변경을 이전 버전과 호환 가능하게 만드는 것입니다. 따라서 새 테이블을 사용하도록 앱을 업데이트하기 전에이 스키마 변경 을 적용 할 수 있습니다. 앱을 업데이트 한 후 이전 열을 삭제하여 두 번째 변경을 적용하여 을 적용 할 수 있습니다. 직장에서, 이것들은 두 가지 다른 릴리스 주기로 수행 될 것입니다. 따라서 릴리스 X 중에는 모든 스키마 변경 사항을 먼저 롤백 할 필요없이 X-1을 릴리스하기 위해 앱을 롤백하는 옵션이 있습니다. 뿐만 아니라 앱 이전에 별도의 창에 스키마 변경 사항을 배포 할 수 있습니다. (기술적으로 나는 이전 테이블에 대한 업데이트가 새 테이블에 동기화되도록 트리거를 작성해야하지만 작업과 너무 비슷하기 때문에 그렇게하지 못했습니다 :))

우리는 데이터베이스를 통해 schema_version 테이블에있는 내용을 확인하고 변경 사항을 추적하므로 사람들은 연결하지 않고 변경된 사항을 확인하고 각 변경 내역에 대한 아이디어를 얻을 수 있습니다 ("dev에 롤백 됨", " dev "등).직장에서 우리 schema_version 테이블에는 저자 정보 등이 포함됩니다. 버전 관리에서 버전 정보를 적용하는 마법 같은 방법은 멋지습니다. 우리가 가진 한 가지 문제는 SC가 QA에 적용되면 예를 들어 PERFORCE에서 변경된 것입니다. 고지. 그래서 개정판 # 4가 적용된 스키마 변경을 추적하는 방법은 좋을 것입니다.

우리에게있어서 스키마 변경 사항은 응용 프로그램 버전과 별개로 번호가 매겨집니다. 분명히 그것들은 관련되어 있습니다 --- 스파이더 링 앱으로 사람들이 입력 할 수있는 또 다른 것입니다. 그러나 우리는 거대한 "여기에 릴리스 X의 모든 것"패치 대신 많은 작은 변화를 주려고합니다. 스키마 변경은 새 인덱스를 추가하는 것과 같은 용도로도 사용되기 때문에 전혀 응용되지 않습니다. 일반적으로 스키마 변경은 DBA가 아닌 개발자가 "소유"합니다. 위의 "create index"예제에서 DBA는 기본적으로 개발자 역할을 수행하고 스키마 변경을 소유합니다. 네, 회사의 다른 그룹이 약간 다르게 작업하고 DB 팀에 더 많은 작업을 제공하기는하지만 개발자의 높은 수준의 SQL 기능을 요구합니다.

+0

고맙습니다 aragnid. 우리 회사에서도 개발자 역할은 적절한 스키마 패치를 만드는 것을 포함합니다. 단일 프로세스가 실제로 패치를 처리하는 데 사용됩니다. 나는 schema_version 테이블에 대한 아이디어가 마음에 든다. 우리는 나의 직장에서 그것을 토론하고 그 중 하나를 사용하는 것을 보았다. – chadl