views:

71

answers:

5

8-byte integers are now the default for Postgres 8.4, so it allows microsecond values to be stored.

I don't care too much about real microsecond precision (probably depends on OS capabilities?!) - But does Postgres guarantee, that the timestamp values (inserted by current_timestamp) are always different between any two transactions?

+1  A: 

Even if it does, it seems dangerous to rely on the values being unique. If you need a unique key you are better off using an alternative such as a serial column.

Justin Ethier
I'd love to do that - but my use case seems to require that: I want to use a version field in JPA that is globally at least mostly ascending, to improve performance (not just within an entity). But JPA unfortunately doesn't allow me to use a serial column, a sequence or a sequence table for a version field. But it does allow me to use a timestamp, and with JPA, I can safely assume the version field to be ascending (for an entity), as long as the database guarantees uniqueness.
Chris Lercher
+1  A: 

Yes, precision depends on the OS. Within a single transaction the timestamps are all the same when using CURRENT_TIMESTAMP, when using CLOCK_TIMESTAMP they might be different. Different transactions can have different CURRENT_TIMESTAMPS, depends on how fast you can insert/update.

If you need uniqueness, add a unique constraint.

Frank Heikens
The unique constraint is a good idea, but one transaction can insert multiple instances in a table - so it would violate the uniqueness. It's ok for my application to have the same timestamp, but not when inserted by different transactions.
Chris Lercher
Do some tests to see if you can insert/update fast enough to get problems.
Frank Heikens
@Frank: Yeah, this is really a situation, where I'd have a simple, super-fast solution (for the version management in my distributed app), but at the price of a small chance of errors. Or on the other hand a solution, which would make the app much slower, and increase traffic by a significant factor - but it would be more correct...
Chris Lercher
+4  A: 

No.

I did a small test, inserting current_timestamp from 5 parallell clients in a table, 3 of 3463 records got the same timestamp.

nos
Ok, that's the definite answer - I'll have to look for a different solution then. Thanks!
Chris Lercher
+1  A: 

Luckily no, since that would mean a "please make this slower than it has to be" option.

If you really need what is really a serial, but which looks like a timestamp, then add some microseconds on based on the result of a serial!

Jon Hanna
Good point, and a good idea. I wish, JPA would allow me to do that (it manages the timestamps for version fields itself).
Chris Lercher
Why does it insist that a version is unique. That seems like it's doing two jobs from the same thing. Could you add your own version and identity columns yourself and ignore this version+identity feature?
Jon Hanna
@Jon: I hope, I'll find a way to extend/replace JPA's versioning with my own versioning, but I don't think it's easy to do, because it's an integral part of JPA.
Chris Lercher
Do JPA have a way where they completely manage versioning themselves? In which case, just use an integral type.
Jon Hanna
@Jon: Yes, JPA offers integral versioning and timestamp versioning. The problem with integral versioning is, that JPA starts counting at 1 for every entity in the table separately. So I can't do a query `from t where version > 578`, when I want to retrieve all entities that have changed since the last time I checked. Using a sequence (or setting the value myself) would be great, but JPA doesn't seem to allow that.
Chris Lercher
That's a different requirement to versioning though (though slightly overlapping, and sometimes we can do both from the same value). Maybe have a version and a last-mod as separate columns?
Jon Hanna
+1  A: 

I agree with the recommendation of adding a serial. But if what you are trying to do doesn't merit a schema change, you could use the system column xmin to separate rows with the same timestamp but from different transactions.

  SELECT ts, xmin, count(1)
  FROM foo
  GROUP BY ts, xmin
Scott Bailey