CURRENT_TIMESTAMP를 기본 키로 사용할 수 있습니까?


10

CURRENT_TIMESTAMPA와 사용 PRIMARY KEY?

둘 이상의 다른 INSERT가 동일 할 가능성이 CURRENT_TIMESTAMP있습니까?


3
1990 년대에 타임 스탬프를 PK로 사용하여 코딩 된 앱에 대해 들었습니다. 10 년 후 PC가 빨라지고 타임 스탬프가 복제되었습니다. 앱의 기능이 매우 중요했기 때문에 매우 심각한 문제가 발생했습니다. 또한 앱 전체에서 PK 고유성이 제대로 적용되지 않았습니다.
Victor Di Leo 1

둘 이상의 다른 INSERT가 동일한 CURRENT_TIMESTAMP를 얻을 가능성이 있습니까? 충돌을 위해 하나의 쿼리로 2 개의 레코드를 삽입했습니다. 따라서 주제 질문에 대한 대답은 "아니오"입니다.
Akina


3
왜 이걸 원하는지 궁금 하신가요?
Nanne

@Nanne 나는 이것을 의심한다 : MySQL은 자동으로 증가 된 정수 ID (필드에 대한 auto_increment 속성)를 아주 잘 처리했다. PostgreSQL에는 그렇지 않은 직렬 유형이 있습니다.
peterh-복원 모니카

답변:


18

당으로 문서 ,의 정밀도는 CURRENT_TIMESTAMP마이크로입니다. 따라서 충돌 확률은 낮지 만 가능합니다.

이제 아주 드물게 발생하고 데이터베이스 오류 가 발생하는 버그를 상상해보십시오 . 디버깅하기가 얼마나 어렵습니까? 적어도 결정론적인 버그보다 훨씬 나쁜 버그입니다.

더 넓은 맥락 : 아마도 시퀀스에 이러한 작은 뉘앙스를 피하고 싶을 것입니다. 이것은 MySQL에 익숙하다면 특히 성가시다.

또한 트랜잭션 (대부분의 웹 프레임 워크, 특히 Java 프레임 워크)을 사용하는 경우 트랜잭션 내에서 타임 스탬프가 동일합니다! 데모 :

postgres=# begin;
BEGIN
postgres=# select current_timestamp;
       current_timestamp       
-------------------------------
 2018-08-06 02:41:42.472163+02
(1 Zeile)

postgres=# select current_timestamp;
       current_timestamp       
-------------------------------
 2018-08-06 02:41:42.472163+02
(1 Zeile)

만나요? 두 가지 선택, 정확히 같은 결과. 나는 너무 빨리 입력하지 않습니다. ;-)

-

시퀀스를 사용하지 않고 쉽게 ID를 원하면 레코드의 실제 식별자에서 일부 해시 값을 생성하십시오. 예를 들어, 데이터베이스에 사람이 있고 생년월일, 어머니의 성함 및 실명이 고유하게 식별된다는 것을 알고 있다면

md5(mother_name || '-' || given_name || '-' birthday);

id로. 그 외에도 CreationDate테이블을 색인화 한 후에 열을 사용할 수 있지만 키 (ID)는 아닙니다.

시는 일반적으로,이다 매우 좋은 연습 이 가능한 한, 당신의 DB 그렇게 결정하게. 즉 , 동일한 작업이 DB에서 정확히 동일한 변경 사항을 생성해야합니다 . 타임 스탬프 기반 ID가이 중요한 기능에 실패합니다. 디버그하거나 시뮬레이션하려면 어떻게해야합니까? 작업을 재생하면 동일한 ID로 다른 ID로 생성됩니다 ... 실제로 따르기가 어렵지 않으며 많은 작업 시간이 필요합니다.

Ps2 앞으로 코드를 확인하는 사람은 위의 이유로 타임 스탬프 생성 ID를 보는 가장 좋은 의견을 얻지 못할 것입니다.


트랜잭션을 사용하지 않더라도 실제로 트랜잭션을 사용하고 있습니다 (Postgres에는 트랜잭션 없음 모드가 없으므로 자동 커밋 만 있음). 따라서 INSERT여러 행 을 수행하면 모두 동일 current_timestamp합니다. 그리고 당신은 방아쇠가 있습니다 ...
Kevin

2
나는 두 사람이 같은 이름을 가지고 같은 날에 태어 났고 그들의 어머니 이름이 동일했기 때문에 고장난 앱에 대해 들었습니다. 아야. 그것이 일어날 수 있다면 조만간 일어날 것입니다.
Balazs Gunics

@BalazsGunics Helló :-) 예제 일뿐입니다. 예를 들어 실제 시나리오에서는 id를 이메일 주소 또는 선택한 사용자 이름 (아직 존재하지 않는 경우에만 등록 할 수 있음)으로 충분하다고 생각합니다. 정부는 1 870728 0651과 같은 개인 식별 번호를 사용하는 경향이 있습니다. 중요한 것은 ID를 타임 스탬프 또는 임의의 값에 바인딩하는 것은 DB를 결정적이지 않기 때문에 나쁜 습관입니다.
peterh-Reinstate Monica

@BalazsGunics 동일한 mother_name + given_name + 생일을 가진 두 사람 외에는 여전히 결정적인 오류가 발생합니다. 인서트가있는 두 트랜잭션이 동일한 마이크로 초에 발생했기 때문에 기본 키 충돌이 발생하지만 여전히 결정적이지 않고 재현하기 어려운 문제입니다.
peterh-Reinstate Monica

10

CURRENT_TIMESTAMP가 두 개의 후속 INSERT (또는 여러 행이있는 단일 INSERT)에 대해 동일한 두 개의 값을 제공 할 수 있기 때문에 실제로는 아닙니다.

대신 시간 기반 UUID를 사용하십시오 ( uuid_generate_v1mc ()) .


7

엄밀히 말하면 : 아니요CURRENT_TIMESTAMP . 함수 이기 때문에 하나 이상의 테이블 열만PRIMARY KEY 제약 조건을 형성 할 수 있습니다 .

PRIMARY KEY기본값으로 열에 제약 조건 을 만들려는 CURRENT_TIMESTAMP경우 대답은 다음과 같습니다. 예, 가능 합니다. 아들의 머리에서 사과를 쏘지 못하게하는 것처럼 아무것도하지 않습니다. 질문의 목적을 정의하지 않으면 질문은 여전히 ​​타당하지 않습니다. 열과 테이블에는 어떤 종류의 데이터가 있어야합니까? 어떤 규칙을 구현하려고합니까?

일반적으로 동일한 트랜잭션 (트랜잭션의 시작 시간)에 대해 동일한 값을 반환 CURRENT_TIMESTAMP하는 STABLE함수 이므로 아이디어는 중복 키 오류가 발생합니다 . 동일한 트랜잭션의 여러 INSERT는 이미 설명 된 다른 답변과 마찬가지로 충돌 할 수밖에 없습니다. 매뉴얼 :

이러한 함수는 현재 트랜잭션의 시작 시간을 반환하므로 해당 값은 트랜잭션 중에 변경되지 않습니다. 이는 하나의 기능으로 간주됩니다. 의도는 단일 트랜잭션이 "현재"시간에 대해 일관된 개념을 갖도록하여 동일한 트랜잭션 내에서 여러 수정이 동일한 타임 스탬프를 갖도록하는 것입니다.

Postgres 타임 스탬프는 최대 6 개의 소수 자릿수 (마이크로 초 해상도)를 나타내는 8 바이트 정수로 구현됩니다.

경우 (이름이 뭔가를 당신이 마이크로 당 하나 이하의 행을 보유하도록되어 테이블을 구축하고 해당 조건이 변화하지 않을 sensor_reading_per_microsecond), 다음 이 적합 할 수 있습니다. 중복 행이되는 가정 중복 키 위반 오류가 발생 할 수 있습니다. 그러나 이것은 이국적인 예외입니다. 그리고 데이터 유형 timestamptz(not timestamp)이 바람직 할 것입니다. 보다:

대신 여전히 대리 직렬 기본 키를 사용하고 싶습니다. UNIQUE타임 스탬프 열에 제약 조건을 추가하십시오 . RDBMS의 구현 세부 사항에 의존하지 않고 가능한 복잡성 감소.


sensor_reading_per_microsecond각 판독 값의 타이밍이 이전 판독 값과 완벽하게 동기화되었다고 절대 보장 할 수없는 경우 에도 충돌 할 수 있습니다. 1 마이크로 초 미만의 편차 (종종 불가능하지는 않음)는 구성표를 위반합니다. 일반적으로 나는 여전히 이것을 완전히 피할 것입니다. (당신이 지적했듯이, 그런 경우, 결과적인 충돌이 바람직 할 수 있습니다!)
Orbit in Orbit

@Lightness : 나는 완전히 동의하고 있습니다. 둥글고 작은 편차 후 의도하지 않은 시간 이동이있는 예는 또 다른 경고를 보여줍니다.
Erwin Brandstetter
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.