Does anyone have experience they can share using MySQL savepoints (directly or via an ORM), especially in a non-trivial web service? Where have you actually used them? Are they reliable enough (assuming you're willing to run a fairly recent version of MySQL) or too bleeding-edge or expensive?
Lastly, does anyone have experience with something like the following use case and did you use savepoints for it? Say the main point of some specific unit of work is to add a row to an Orders
table (or whatever, doesn't have to be order-related, of course) and update an OrdersAuditInfo
table, in the same transaction. It is essential that Orders
be updated if at all possible, but OrdersAuditInfo
table is not as essential (e.g., it's ok to just log an error to a file, but keep going with the overall transaction). At a low level it might look like this (warning, pseudo-SQL follows):
BEGIN;
INSERT INTO Orders(...) VALUES (...);
/* Do stuff outside of SQL here; if there are problems, do a
ROLLBACK and report an error (i.e., Order is invalid in this
case anyway). */
SAVEPOINT InsertAudit;
INSERT INTO OrdersAudit(...) VALUES(...);
/* If the INSERT fails, log an error to a log file somewhere and do: */
ROLLBACK TO SAVEPOINT InsertAudit;
/* Always want to commit the INSERT INTO Orders: */
COMMIT;
But even here perhaps there'd be a better (or at least more common) idiom? One could do the OrdersAuditInfo
insert in a completely different transaction but it would be nice to be guaranteed that the OrdersAuditInfo
table were not written to unless the final COMMIT
actually worked.
I believe you are using a savepoint to avoid failed
INSERT
s to rollback the whole transaction. But in that case, the best way to do so is to useINSERT IGNORE
. If it fails you will get a warning instead of an error, and nothing will rollback.Since you don't need a rollback, I suggest you don't use a transaction.
SAVEPOINT
s are great if you may want to rollback some successful statements (but not all statements). For example:If the
SELECT
returns nothing, you may run a globalROLLBACK
. If any of the following INSERTs fails, you mayROLLBACK TO SAVEPOINT one
and pick anotherid
. Obviously, in a case like this, you want to implement a maximum number of attempts in your code.