DaedalusFall
DaedalusFall

Reputation: 8575

Can I bypass the current transaction in MySQL?

I have some (php) code that performs critical updates on an InnoDB table.

I'm using (SELECT ... FOR UPDATE), so I need to be inside a transaction.

This code is being executed when data is posted from a form, and I have a message system in place so that error/success messages are stored in a database, and extracted from the database next time a page is rendered.

Some pseudocode: (I'm ommitting stuff like the try/catch blocks and escaping that I have in my real code)

beginTransaction();

query("SELECT * FROM `table` WHERE id=1 FOR UPDATE");

$x=$_POST[$x];
query("UPDATE `table` SET `field` = $X");

//add other data in the db related to $X
query("INSERT INTO `othertable` (x,y,x) VALUES (......)");


//check for various errors...
$erros=0

if ($error_condition_1) {
    messageSystem("Error Condition 1!")
    $errors+=1;
}
if ($error_condition_2) {
    messageSystem("Error Condition 2!")
    $errors+=1;
}

if ($errors) {
    rollBackTransaction();
} else {
    commitTransaction();
}

The problem should be obvious: when messageSystem stores the error in the database the changes will be rolled back later, and the user will never see the error messages.

There are two easy solutions I can see:

  1. Modify my code so that messageSystem is called outside the transaction. However it is more readable and quicker to write if I can do it inline like the above. Also, what if this is library code that may already be inside a nested transaction?
  2. Modify messageSystem so that it uses its own connection to the database. But then what if I make messageSystem more complicated, and decide that it needs to lock an entry in the session table before it adds messages to that session. This could lead to a deadlock if my main code has also locked the session for some reason.
  3. Check for errors before the transaction. But in actual fact I need to have locked the relevant rows by selecting 'FOR UPDATE' before I can validate the input.

And so my question: Is there any way to commit X when inside a (possibly nested) transaction such that if the transaction is rolled back, X will be committed anyway.

Alternatively is there any good way of avoiding the problem I've described.

Thanks!

Upvotes: 3

Views: 406

Answers (1)

mikebabcock
mikebabcock

Reputation: 791

The simple answer is to use a second database connection for your error logging.

Upvotes: 2

Related Questions