관계형 데이터베이스 (예 : PostgreSQL)에 대한 트리거가 실제로 필요합니까?


10

데이터베이스를 일관성있게 유지하기 위해 트리거를 사용하여 저장된 데이터의 유효성을 검사 할 수 있습니다. 그러나 데이터베이스에 데이터를 저장하기 전에 애플리케이션 측에서 데이터 유효성 검증을 수행하지 않는 이유는 무엇입니까?

예를 들어 클라이언트를 저장하고 DDL 수준에서 쉽게 수행 할 수없는 일부 유효성 검사를 수행하려고합니다. https://severalnines.com/blog/postgresql-triggers-and-stored-function-basics

또 다른 예는 감사입니다.

최신 정보

트리거와 데이터베이스 트랜잭션이 함께 작동하는 방식 예를 들어 삽입되는 데이터의 유효성 검사를 수행하려는 경우. 트랜잭션 내부에서 수행됩니다. 이전에 수행 된 작업 : 트랜잭션이 커밋되거나 트리거가 실행됩니까?


However, why not perform validation of data on the application side before storing them into the database?글쎄,이 둘은 상호 배타적이지 않다. 양쪽에서 다른 것들을 검증 할 것입니다. 응용 프로그램의 유효성 검사는 비즈니스 중심이지만 데이터베이스의 유효성 검사는 데이터 중심입니다. 여러 다른 응용 프로그램에서 제공하는 데이터베이스를 생각해보십시오.
Laiv

당신은 당신의 시스템에 그냥 데이터 덤프를하고 외부 소스에서 데이터를 삽입해야합니까? 그렇다면 나중에 정정하기 위해 데이터를 유효하지 않은 형식으로 삽입해야하는 경우가 있습니다. 이 경우 트리거는 끝없는 문제를 유발합니다. 이것을 명심하십시오. 때로는 트리거가 실행되기를 원하지 않습니다 .
Greg Burghardt

귀하의 업데이트는 자체적으로, 아마도 SO에 대한 질문이어야하지만 귀하의 질문은 이미 Database Administrators.SE 에 대한 답변입니다 . 간단히 말해서 트랜잭션이 커밋되기 전에 "업데이트 후"트리거가 실행되고 트리거 내부에 예외가 발생하면 롤백이 발생합니다.
Doc Brown

@GregBurghardt 대부분의 데이터베이스에는 이러한 종류의 활동에 대한 트리거를 비활성화하는 데 사용할 수있는 명령문이 있습니다.
Blrfl 2019

1
@Blrfl : 예. 그러나 현재 세션에 대한 검사를 조건부로만 비활성화하려는 경우 연결된 모든 사용자에 대해 해당 트리거를 일시적으로 비활성화 할 수 있습니다.
Greg Burghardt

답변:


12

어떤 종류의 응용 프로그램 시스템을 구축하고 있는지에 따라 다릅니다.

  • 이 응용 프로그램 전용 데이터베이스와 함께 하나의 기본 응용 프로그램 만 포함하고 응용 프로그램과 데이터베이스를 나란히 개발하는 팀이 이상적인 응용 프로그램 중심 시스템을 만드는 경우 모든 유효성 검사 논리를 유지하고 감사 할 수 있습니다 응용 프로그램 내부의 논리.

    이것의 주요 이점은 응용 프로그램과 db간에 비즈니스 로직을 분배 할 필요가 없으므로 시스템을 유지 보수 및 전개하는 것이 더 쉬워진다는 것입니다. 또한 응용 프로그램을 특정 유형의 DBMS 또는 DBMS 공급 업체에 너무 많이 묶지 않습니다. 애플리케이션이 트리거를 제공하지 않는 경량 DB 시스템을 사용하려면이 방법이 필요합니다.

  • 그러나 많은 다른 응용 프로그램이 공통 데이터베이스를 공유하는 시스템을 만들고 향후에 어떤 응용 프로그램에 쓸 것인지 또는 앞으로 팀에 데이터를 채우기위한 응용 프로그램을 개발할 팀을 미리 계획 할 수없는 경우 데이터베이스가 가능한 한 많은 데이터 일관성을 보장해야합니다. 그리고 그것이 방아쇠가 정말로 도움이되는 곳입니다. 더 큰 시스템에서는 참조 제한이 충분하지 않은 경우가 많지만 저장 프로 시저를 호출하는 트리거는 필요한 모든 종류의 유효성 검사를 구현할 수 있습니다.

트리거를 사용하는 또 다른 이유는 성능 일 수 있습니다. 복잡한 데이터 모델에서는 클라이언트 애플리케이션에서 사용 가능한 현재 작업 세트의 일부가 아닌 많은 추가 데이터를 사용해야하는 복잡한 일관성 규칙이 자주 발생하지 않습니다. 클라이언트 측에서 검증이 가능하도록 네트워크를 통해 모든 데이터를 먼저 전송하면 성능에 큰 영향을 줄 수 있습니다.

이 이전 SE 게시물 : 데이터베이스 정리를위한 Application Logic Vs DB 트리거 참조

따라서 어떤 종류의 시스템을 구축하고 있는지 결정한 다음 트리거가 귀하의 경우에 적합한 도구인지 여부를 결정하십시오.


3

질문은 데이터 품질에 대한 책임에 관한 것입니다.

대답은 시스템을 보는 방법에 따라 다릅니다.

데이터베이스가 응용 프로그램과 별 개인 독립적이고 고유하며 자율적 인 서비스 인 경우 데이터베이스는 데이터베이스에 포함 된 데이터의 일관성과 품질을 보장해야합니다. 기본적으로 해당 데이터베이스를 다른 응용 프로그램에서 사용할 수 있기 때문에 일관성과 품질이 동일한 두 번째 응용 프로그램에 의존 할 수 없습니다. 이러한 상황에서 데이터베이스는 API 및 자율적 인 동작을 노출하도록 설계되어야합니다. 이보기에는 최소한 두 개의 응용 프로그램이 있습니다. 그 중 하나는 데이터베이스이고 다른 하나는이를 사용하는 응용 프로그램입니다.

반대로 데이터베이스는 응용 프로그램을 직접적이고 완벽하게 제어하는 ​​복잡한 파일 형식으로 간주 될 수 있습니다. 이런 의미에서 데이터베이스는 순수한 직렬화 및 문서 탐색 도구가됩니다. 쿼리 및 문서 유지 관리 (JSON 또는 XML 도구와 같은)를 지원하는 몇 가지 고급 동작을 제공 할 수 있지만 (대부분의 파일 스트림처럼) 다시 할 필요는 없습니다. 이 경우 파일 내에서 올바른 형식과 내용을 유지하는 것은 전적으로 프로그램의 책임입니다. 이보기에는 하나의 응용 프로그램이 있습니다.

두 가지 관점에서 다음 질문은 데이터베이스 사용을 멋진 파일 또는 별도의 서비스로 지원하는 방법입니다. 이를 통해 다음을 달성 할 수 있습니다.

  • 데이터베이스 플랫폼이 테이블 / 뷰 / 저장 프로 시저 / 트리거 / 등의 형태로 제공하는 도구 사용
  • 모든 클라이언트가 데이터베이스에 액세스하기 위해 사용해야하는 서비스 내에서 데이터베이스 자체 랩핑
  • 데이터에 액세스하기 위해 모든 클라이언트가 사용해야하는 라이브러리에 데이터베이스를 래핑합니다.

각각에는 장단점이 있으며 시스템이 작동하는 환경의 구조적 제약에 따라 달라집니다.

어떤보기를 사용하든 항상 경계에서 데이터의 유효성을 검사하기 위해 비용을 지불합니다.

  • 사용자가 입력 한 UI에서 필드의 유효성을 검사합니다
  • 클라이언트를 떠나기 전에 네트워크 / API 요청의 유효성을 검사하십시오
  • 작업을 수행하기 전에 서버에서 네트워크 / API 요청을 확인하십시오.
  • 비즈니스 규칙으로 전달되는 데이터의 유효성 검사
  • 지속되기 전에 데이터 유효성 검사
  • 지속성에서 검색된 후 데이터 유효성 검증
  • 등등

각 경계에서 얼마나 많은 검증이 보증되는지는 그것을 검증하지 않는 것이 얼마나 위험한 지에 달려 있습니다.

  • 두 숫자를 곱하면?
    • 당신은 잘못된 숫자가 문제입니까?
  • 주어진 메모리 위치에서 프로 시저를 호출합니까?
    • 그 메모리 위치에 무엇입니까?
    • 개체가 존재하지 않거나 상태가 좋지 않으면 어떻게됩니까?
  • 한자를 포함하는 문자열에 정규식을 사용합니까?
    • 정규식 모듈이 유니 코드를 처리 할 수 ​​있습니까?
    • 정규식으로 유니 코드를 처리 할 수 ​​있습니까?

유효성 검사 논리를 중앙 집중화하는 것은 좋지만 imho 트리거는이를 구현하는 좋은 방법이 아닙니다. 여러 응용 프로그램이 모두 데이터베이스를 공유하고 트리거 및 저장 프로 시저를 통해 데이터베이스에 모든 유효성 검사 논리 및 부작용이 구현 된 시스템에서 작업했습니다. 데이터베이스 앞에 마이크로 서비스를 설치하고 모든 로직을 구현하는 것이 더 낫다는 인상을 받았습니다. SQL 데이터베이스 내부의 사소한 논리는 안티 패턴입니다.
Joeri Sebrechts

1
@JoeriSebrechts 좋아, 나는 물릴 것이다 : 데이터베이스의 사소한 논리가 반 패턴입니까? 그리고 별도로 유지 관리되는 프로그램에 넣는 것보다 반 패턴이 더 중요한 이유 는 무엇입니까?
Blrfl

@Blrfl 두 가지 이유로, DB의 로직에 액세스하기위한 API가 웹 서비스 API보다 열등하고 (버전이 더 어렵고, 사용하기가 어렵고, 쉽게 캐시되지 않음), 데이터베이스를 사용하여 데이터베이스를 깔끔하게 구성하고 유지하기가 더 어렵습니다. 내부에서 호스팅되는 코드베이스. 내 경험에 따르면 데이터베이스 내부보다 데이터베이스 앞에서 웹 서비스에서 논리를 호스팅하는 것이 더 쉽습니다.
Joeri Sebrechts

@JoeriSebrechts 필자는 대부분의 데이터베이스 플랫폼이 신뢰할 수 있고 유용하며 개발 가능한 API를 구현하기위한 훌륭한 도구를 제공한다고 동의합니다. 여러 가지면에서 많은 고통을 느끼는 것은 분명 초대입니다. 필자의 요점은 DB가 멋진 파일임을 깨달았거나 진정으로 별도의 서비스라는 점이 관점에 관한 것이며, 그 스타일의 사용을 지원하기 위해 랩핑하는 방법에 대한 다음 질문으로 이어진다는 것입니다. 나는 그것을 명확하게하기 위해 대답을 정교하게 할 것입니다.
Kain0_0

2

아니요, 유효성 검사를 위해 트리거를 사용해서는 안됩니다.

데이터베이스는 자체 무결성에 대해서만 책임이 있습니다. 유효성 검사에 직면 한 모든 사용자는 응용 프로그램에서 수행해야합니다.

데이터베이스는 무결성을 위해 세 가지 수준의 유효성 검사를 수행합니다. 첫 번째는 필드 레벨 검증입니다. 값이 없으면 필드가 필요할 수 있습니다 (널). 점검 제한 조건이 될 수도 있습니다. 도메인에는 열거 된 수의 값이 있습니다.

두 번째로 테이블간에 관계가 있습니다. 한 테이블에서이 테이블을 다른 테이블과 관련시키고 값이 "다른 테이블"에 유효한 키가되도록 요구하는 하나 이상의 외래 키를 저장합니다. 다른 국가의 주소를 지원하는 주소 데이터베이스를 생각해보십시오. 주소의 국가 키는 알려진 국가를 가리켜 야합니다. 데이터 (예 : 우편 번호)가 유효한지 여부는이 무결성 검사와 관련이 없습니다.

셋째로 가장 복잡한 것은 트리거입니다. 일반적으로 이들은 조건부 인 무결성 규칙에 대해 다루어야합니다. 주소 예로 돌아가려면 : 국가에 우편 번호가없는 경우이 목록의 국가에 우편 번호가 있으면 문제가됩니다. 따라서이 국가에 우편 번호가없는 경우 우편 번호 필드는 null이어야합니다.

유효성 검사는 응용 프로그램의 관심사입니다. 독일 우편 번호가 숫자만으로 구성되어 있다는 사실은 응용 프로그램이 데이터베이스가 아니라 확인해야한다는 것입니다. 회선은 얇기 때문에 어떤 경우 트리거 (데이터베이스의 무결성을 보호) 또는 응용 프로그램 (유저 검증에 직면 한)에 있어야하는 경우 일부 사고 / 토론이 필요할 수 있습니다.


OP가 데이터베이스에 있어야하는 복잡한 유효성 검사 규칙을 추가해야하는 경우 항상 저장 프로 시저를보다 안전한 대안으로 사용할 수 있다고 덧붙였습니다.
Borjab

@Borjab : 데이터베이스를 올바르게 유지하는 것과 같은 유효성 검사. 그러나 사용자가 유효성 검사에 직면하고 있습니까? 호
메노 Hölscher

1
첫 번째 문장은 "검증을 위해 트리거를 사용하지 마십시오"라고 말하지만 아래에 "예, 특정 종류의 유효성 검사에 트리거를 사용할 수 있으며 선을 그릴 위치가 명확하지 않습니다"라고 적습니다. 이것은 상당히 모순된다. 첫 문장을 삭제하면 답이 크게 향상됩니다. 아, 그리고 마지막 문장은 "전후"가 거래와 관련이 없기 때문에 OP 업데이트 질문에 대답하지 않습니다. 삭제하는 것이 좋습니다. (OPs 질문 아래의 내 의견 참조).
Doc Brown

@DocBrown 차이점은 데이터베이스를 손상으로부터 보호하는 것과 사용자를 대상으로하는 유효성 검사입니다. 따라서 "추가 검증"에서 사용자 대면 검증을 참조합니다. 이 구분을 더 명확하게하려면 어떻게해야합니까? 처음에는 "추가"를 제거했습니다.
Menno Hölscher

2
데이터베이스에서 유효성 검사를 수행하는 것이 좋습니다. 응용 프로그램에서 수행하는 것이 좋습니다. 둘 다 장점이 있습니다. 응용 프로그램에서 유효성 검사를 수행한다는 것은 ORM없이 SQL을 실행할 때마다 거의 모든 복잡한 응용 프로그램에 필요한 매우 신중해야한다는 것을 의미합니다.
Qwertie

1

감사는 트리거를 효과적으로 사용하는 전형적인 예입니다. 트리거로 구현 된 감사 테이블 덕분에 테스터가 클라이언트를 한 수준의 서비스에서 다른 수준으로 이동시키는 데 따른 오류를 발견했습니다. 감사를 위해 트리거를 사용하는 것이 좋습니다.

프런트 엔드 수준에서 유효성 검사를 수행 수는 있지만 처리 한 데이터베이스 (3000에서 태어난 사람들 등)에서 이상한 오류가 발생했으며 그중 일부이기 때문에 추가 계층을 갖는 것이 좋습니다. 만일의 경우를 대비하여 데이터베이스에서 유효성 검사 물론 이러한 유형의 오류는 검사 제한 조건으로 피할 수 있으며 여러 번 더 효과적입니다 (MS SQL에서는 선호되는 방법입니다. 항상 문서를 확인하십시오).


1

관계형 데이터베이스에 대한 트리거가 실제로 필요한지에 대한 질문이므로 트리거를 사용하는 다른 사용 사례가 있습니다.

  1. 다른 답변에 설명 된대로 감사합니다.
  2. 보다 넓은 의미의 감사 : 데이터베이스 항목이 변경되면 트리거는 비동기적인 사후 처리를 위해 이벤트를 기록 할 수 있습니다 (예 : 다른 애플리케이션으로 야간 내보내기).
  3. 뷰에 대한 트리거 : 트리거를 정의 할 수 있습니다 instead of. 따라서 뷰에서 항목을 삽입, 업데이트 및 삭제할 수 있습니다. 트리거는 이러한 조치를 여러 테이블에 분산시킬 수 있습니다. 이는 기본 테이블의 세부 사항을 노출시키지 않고 제한된보기를 사용 가능하게하는 방법입니다.
  4. 데이터베이스 전환을 명시 적으로 저장하려면 : 테이블 A와 B와 중간 테이블 R 사이의 N : M 관계를 가정합니다. R에서 A와 B 사이의 외래 키 제약 조건을 정의 할 수 있습니다. B의 해당 항목이 삭제됩니다. 그러나 비즈니스 논리에 따라 A의 항목이 B의 항목과 하나 이상의 관계를 가져야하는 경우가 있습니다.이 경우 R 삭제시 트리거가이 논리를 적용하는 데 도움이 될 수 있습니다. A의 항목의 경우 R의 마지막 항목 애플리케이션 중심 뷰에서 적어도 두 번의 전환이 필요합니다. 이것은 유효성 검사의 예입니다. 다른 사례도 생각할 수 있습니다 : 사용 사례 (1), (2),
  5. 신뢰 : 때때로 데이터베이스 관리자가 응용 프로그램을 사용하지 않는 명령 행에서 항목을 변경합니다. 관리자는 신중하게 작업하고 자신이하는 일을 알고 있습니다. 그러나 때로는 틀릴 수도 있습니다. 일관성이 중요한 경우 트리거는 안전 벨트입니다.

단점은 비즈니스 로직이 계층간에 분산되므로 유지 관리에 대한 주요 단점입니다. 다른 저자가 쓴 것처럼, 응용 프로그램과 데이터베이스 사이의 경계가 좁고 선택이 항상 명확한 것은 아닙니다. 내 개인적인 의견은 트리거가 개발자에게 부담이된다는 것입니다. 개발 시간을 절약 할 수 있습니다. 그들은 느린 네트워크 연결을 통해 성능을 향상시키기 때문에 사용자 경험을 향상시킵니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.