CURRENT_TIMESTAMP, BİRİNCİL ANAHTAR olarak kullanılabilir mi?


10

Can CURRENT_TIMESTAMPbir olarak kullanılabilir PRIMARY KEY?

İki veya daha fazla farklı INSERT'in aynı olma olasılığı var mı CURRENT_TIMESTAMP?


3
1990'larda zaman damgası kullanılarak PK olarak kodlanmış bir uygulama duydum. On yıl sonra bilgisayarlar daha hızlı hale geldi ve zaman damgaları çoğaltıldı. Bu, uygulamanın işlevselliği son derece kritik olduğundan çok ciddi sorunlara neden oldu. Ayrıca, PK benzersizliği uygulama boyunca doğru bir şekilde uygulanmadı.
Victor Di Leo

İki veya daha fazla farklı INSERT'in aynı CURRENT_TIMESTAMP'ı alma olasılığı var mı? Bir sorgu çarpışma için 2 kayıt ekledi yeterlidir. Dolayısıyla, bir konuya verilen sorunun cevabı "HAYIR" dır.
Akina


3
Bunu neden isteyeceğini merak ediyorum?
Nanne

@ Bundan şüphe ediyorum: MySQL otomatik olarak artan tamsayı kimlikleri (yalnızca alana otomatik_increment özniteliği) çok güzel bir işleme sahiptir. PostgreSQL'in sahip olmadığı, çok daha az güzel olan bir seri tipi vardır.
peterh - Monica'yı geri yükle

Yanıtlar:


18

Gereğince belgelerin , hassas CURRENT_TIMESTAMPmikro saniyedir. Bu nedenle, bir çarpışma olasılığı düşüktür, ancak mümkündür.

Şimdi çok nadiren meydana gelen ve veritabanı hatalarına neden olan bir hata düşünün . Hata ayıklamak ne kadar zor? En azından deterministik olandan çok daha kötü bir hatadır.

Daha geniş bağlam: dizilerle bu küçük nüanslardan kaçınmak istersiniz, bu da MySQL'e alışkınsanız özellikle can sıkıcıdır.

Ayrıca, işlemleri kullanıyorsanız (çoğu web çerçevesi, özellikle de Java olanları!), Zaman damgaları bir işlem içinde aynı olacaktır! Bir gösteri:

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)

Görüşürüz? İki seçim, aynı sonuç. Çok hızlı yazmıyorum. ;-)

-

Kimlikleri kullanmaktan kaçınarak kolayca kimlikler istiyorsanız, kayıtların gerçek tanımlayıcılarından bir karma değer oluşturun. Örneğin, veritabanınızda insanlar varsa ve doğum tarihlerinin, annenin kızlık adının ve gerçek adının onları benzersiz bir şekilde tanımladığını biliyorsanız,

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

id. Bunun yanı sıra CreationDate, tabloyu dizine ekledikten sonra bir sütun kullanabilirsiniz , ancak bu bir anahtar değildir (id).

Ps Genel olarak, DB mümkün olduğunca deterministik yapmak için çok iyi bir uygulamadır . Yani aynı işlem DB'de aynı değişikliği yaratmalıdır . Zaman damgası tabanlı herhangi bir kimlik bu önemli özellikte başarısız olur. Hata ayıklamak veya herhangi bir şeyi simüle etmek isterseniz ne olur? Bir işlemi yeniden oynatırsınız ve aynı nesne farklı bir kimlikle oluşturulur ... takip etmek gerçekten zor değildir ve çok fazla çalışma saati harcar.

Ps2 Kodunuzu gelecekte kontrol eden herkes, yukarıdaki nedenlerle zaman damgası tarafından oluşturulan kimlikleri görmek için en iyi fikre sahip olmayacaktır.


İşlemleri kullanmasanız bile, aslında işlemleri kullanıyorsunuzdur (Postgres'in işlemsiz modu olmadığı için sadece otomatik taahhüdü vardır). INSERTBirden çok satırdan birini yaparsanız , hepsi aynı olur current_timestamp. Ve sonra tetikleriniz var ...
Kevin

2
2 adam aynı adı taşıyan ve aynı gün doğan ve anne isimleri aynı olduğu için kırdı bir uygulama duydum. Ahh. Olabilirse, er ya da geç gerçekleşir.
Balazs Gunics

@BalazsGunics Helló :-) Bu sadece bir örnekti. Örneğin, gerçek senaryolarda, bence e-posta adresi veya seçilen kullanıcı adı (yalnızca henüz yoksa kaydedilebilir) olarak kimlik yeterli. Hükümet, 1 870728 0651 gibi bazı kişisel kimlik numaralarını kullanma eğilimindedir. Önemli olan, bir kimliği bir zaman damgasına veya rastgele bir değere bağlamak kötü bir uygulamadır, çünkü DB'yi daha az belirleyici yapar.
peterh - Monica'yı geri yükle

@BalazsGunics Bunun yanı sıra, aynı ana_adı + verilen_adı + doğum günü olan iki kişi hala belirleyici bir hataya neden olacaktır. Aynı mikrosaniyede iki işlemin eklenmesi nedeniyle birincil anahtar çarpışması, hala belirleyici olmayan ve çok zor tekrarlanabilir bir sorundur.
peterh - Monica'yı geri yükle

10

CURRENT_TIMESTAMP için birbirini izleyen iki INSERT (veya birden fazla satır içeren tek bir INSERT) için iki özdeş değer sağlaması mümkün değil.

Bunun yerine zamana dayalı bir UUID kullanın: uuid_generate_v1mc () .


7

Kesinlikle söylemek gerekirse: Hayır. Çünkü CURRENT_TIMESTAMPbir işlevdir ve yalnızca bir veya daha fazla tablo sütunu bir PRIMARY KEYkısıt oluşturabilir .

PRIMARY KEYVarsayılan değere sahip bir sütunda bir kısıtlama oluşturmak istiyorsanız CURRENT_TIMESTAMP, cevap: Evet, yapabilirsiniz . Hiçbir şey, oğlunuzun kafasından elma çekmekten alıkoyacak hiçbir şey yapmanıza engel olmaz. Soru, amacını tanımlamazken yine de anlamlı olmaz. Sütun ve tablonun ne tür veriler tutması gerekir? Hangi kuralları uygulamaya çalışıyorsunuz?

Tipik olarak, aynı işlem (işlemin başlangıç ​​zamanı) için aynı değeri döndüren CURRENT_TIMESTAMPbir STABLEişlev olduğundan , fikir yinelenen anahtar hatalarına neden olur . Aynı işlemdeki birden çok INSERT, daha önce gösterilen diğer yanıtlar gibi çarpışmaya bağlıdır. Kullanım kılavuzu:

Bu işlevler geçerli işlemin başlangıç ​​zamanını döndürdüğünden, işlem sırasında değerleri değişmez. Bu bir özellik olarak kabul edilir: amaç, tek bir işlemin "geçerli" zaman konusunda tutarlı bir fikre sahip olmasını sağlamaktır, böylece aynı işlem içindeki birden fazla değişiklik aynı zaman damgasını taşır.

Postgres zaman damgaları, 6 fraksiyonel basamağı (mikrosaniye çözünürlük) temsil eden 8 baytlık tamsayılar olarak uygulanır.

Eğer (adlandırılmış bir şey sen mikrosaniye başına en fazla bir satır tutmak gerekiyordu bir tablo inşa ediyoruz ve bu koşul değişikliğine gitmiyor sensor_reading_per_microsecond), ardından da mantıklı olabilir. Yinelenen satırlar vardır sözde yinelenen bir anahtar ihlali hatası yükseltmek. Yine de bu egzotik bir istisna. Ve veri tipi timestamptz(değil timestamp) muhtemelen tercih edilir. Görmek:

Bunun yerine bir yedek seri birincil anahtar kullanmayı tercih ederim. Ve UNIQUEzaman damgası sütununa bir kısıtlama ekleyin . RDBMS'nin uygulama detaylarına dayanmayan daha az olası komplikasyon.


sensor_reading_per_microsecondHer okuma zamanlamasının bir öncekine göre mükemmel şekilde senkronize edildiğini kesinlikle garanti edemezseniz bile çarpışabilir; bir mikrosaniye-altı sapma (ki bu genellikle imkansız değildir) şemayı bozar. Genel olarak bundan tamamen kaçınırdım. (Belirttiğiniz gibi, böyle bir durumda, ortaya çıkan çarpışma arzu edilebilir!)
Orbit'teki Hafiflik Yarışları

@Işıklık: Tamamen katılıyorum. Yuvarlatılmış küçük bir sapmadan sonra istenmeyen zaman kayması olan örneğiniz başka bir uyarıyı gösterir.
Erwin Brandstetter
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.