GORM and CockroachDB transaction errors

Hi all,

I’ve been using Cockroach with the GORM ORM, as recommended here:
https://www.cockroachlabs.com/docs/stable/build-a-go-app-with-cockroachdb-gorm.html

It doesn’t seem like a good fit?

GORM made an interesting design decision to wrap all writes in transactions, even if it’s only a single SQL statement.

Unfortunately, Cockroach doesn’t seem to handle transactions reliably, and needs the client to manually handle TransactionRetryError and retry (cf https://github.com/cockroachdb/docs/issues/1587)

Taken together, that means any database write with GORM needs manual retry handling…

I understand the individual design decisions here but the end result seems kind of broken? Is this intended behavior? Or am I misunderstanding the situation? Should the docs on using GORM with Cockroach say something about this?

Thanks,
Nick

Nick, it is true that, depending on your workload, transaction in CRDB can sometimes encounter retriable errors (this is also true, although perhaps to a lower degree, with a lot of other databases too).
The fact that GORM wraps or doesn’t wrap queries in BEGIN; COMMIT; does not matter; we treat a single statement as an “implicit transaction” anyway.

It is also true that, under certain circumstances, we do the retries automatically on the server-side, so the client will not observe them. These circumstances include implicit transactions and transactions for which all the statements arrive to the server as one batch. So the wrapping done by GORM qualifies.
There’s a caveat about queries that produce a lot of results; for those we do not do retries automatically. But, again, the wrapping doesn’t matter; you have the same problem with or without it.

Hi Andrei,

Thanks for the response. That behavior doesn’t match what I’m seeing. I set up a repro case that does the insertions with and without transactions:

Under this workload, insertions in single-statement transactions fail about 1% of the time, and insertions without transactions always succeed. That doesn’t make sense to me.

Should I file a bug about this?

Nick

Hi Nick,

It seems I am able to reproduce the issue as you’ve described with the release binary (v1.0.6).

The discrepancy seems to disappear when I use the binary built from the (current state) release-1.1 branch or the master branch on Github.

I presume it was fixed sometime in between v1.0.6 and v1.1. Perhaps someone else with more context could chime in on the specific fix.

Note that the 1.1 branch is not production-condoned yet, though I’d give it a shot to see if it resolves your issue.

Richard,

Confirmed that last week’s 1.1 beta fixes the problem! The team must have fixed it faster than I could report it :laughing:.

Nick

My last answer was not precise enough. I thought I’d get away with it because the further details are inconsequential. However, the details were… consequential in 1.0; there were further improvements in 1.1.
It has to do with differences between how we handle the queries “BEGIN; ; COMMIT;” depending if they were sent by the client as one “query string” or as three (one per statement). In 1.0, the server was only able to hide retriable errors in the former case. In 1.1 it can hide them in both cases.