My code:
mysql_query("SET AUTOCOMMIT=0");
mysql_query("START TRANSACTION");
insert_query, update_query1, update_query2
mysql_query("COMMIT");
update_query3
Why does update_query3 query doesn't work if I put it after COMMIT? It works if I put it before the COMMIT. Why is that? It's really strange.
Thank you
First you disable auto-commit. Then you begin transaction, make changes and commit them. Then you execute another query that implicitly starts another transaction. In order for changes to get committed, you have to call "COMMIT" explicitly because auto-commit is turned off.
Because COMMIT (or ROLLBACK for that matter) marks the end of the transaction.
You'd have to use:
mysql_query("COMMIT AND CHAIN");
..to create a new transaction to begin as soon as the current one ends, and the new transaction has the same isolation level as the just-terminated transaction.
But it still means you need to have:
mysql_query("COMMIT");
...after the update_query3 to commit the changes.
update_query3 isn't part of any existing transaction. So it starts a new (implicit) transaction.
You never commit the transaction started by update_query3, so it'll get rolled back when you close the connection.
Related
I am for example trying to create a new record in my mysql database. In the case of a sql.ErrTxDone, what does it actually mean, what should i do in-case the transaction was committed ?
You get this error if a transaction is in a state where it cannot be used anymore.
sql.Tx:
After a call to Commit or Rollback, all operations on the transaction fail with ErrTxDone.
And also sql.ErrTxDone:
ErrTxDone is returned by any operation that is performed on a transaction that has already been committed or rolled back.
var ErrTxDone = errors.New("sql: transaction has already been committed or rolled back")
What should you do? Don't use the transaction anymore. If you have further task, do it outside of it or in another transaction.
If you have tasks that should be in the same transaction, don't commit it until you do everything you have to. If the transaction was rolled back (e.g. due to a previous error), you have no choice but to retry (using another transaction) or report failure.
If you're already using transactions, try to put everything in the transaction that needs to happen all-or-nothing. That's the point of transactions. Either everything in it gets applied, or none of them. Using them properly you don't have to think about cleaning up after them. They either succeed and you're happy, or they don't and you either retry or report error, but you don't have to do any cleanup.
I'm doing a SELECT ... FOR UPDATE to lock one record, then doing some calculations and then doing the actual UPDATE. I'm working on an InnoDB-database.
But the calculations might end up in a state where I do not want to execute the UPDATE. How do I cancel the lock in this situation?
InnoDB is made for this. You need to manage your transactions.
Before doing your SELECT ... FOR UPDATE, do START TRANSACTION.
Then do your SELECT ... FOR UPDATE.
Then do the rest of your database work.
Then do COMMIT.
If you decide you don't want to complete your update work, do ROLLBACK instead of COMMIT, and every change within your transaction is discarded. The database returns to the state right before START TRANSACTION.
Don't forget the COMMIT or ROLLBACK especially when debugging. If you do forget, your database may appear to lock up, because a future SELECT ... FOR UPDATE operation may wait for your COMMIT. (Don't ask how I know this. :-)
I want to test a script what it does when MySQL transaction fails. So I want to simulate transaction failure on COMMIT.
Image the script opens a transaction, makes some queries, and then commits the transaction. I want to implant some extra query to the transaction, to ensure the transaction will fail on COMMIT. So I can test how the script recovers from the transation failure.
I don't want to use explicit ROLLBACK. I want to simulate some real-life case when a commit fails. The exact DB structure is unimportant. It may adapt to the solution.
Edit: I need the transaction to fail on COMMIT, not on some prior query. Therefore answers that rollback prior to COMMIT are not what I want. Such as this one: How to simulate a transaction failure?
My unsuccessful attempts:
Inserting a row with invalid PK or FK fails immediately with insert. Temporarily disabling FK checks with FOREIGN_KEY_CHECKS=0 won't help as they won't be rechecked on COMMIT. If it was psql, defferable constraints would help. But not in mysql.
Opening two parallel transactions and inserting a row with the same PK (or any column with unique constaint) in both transactions locks the later transaction on insert and waits for the former transaction. So the transaction rolls back on insert not on commit.
So I believe you can try the following
Two phase commit : Use two database ( First and second) and make
use of two phase commit. When the commit statement is supposed to be
executed you can shutdown the second db. This way your commit
operation will fail and transaction will rollback.
You executed several inserts and before your commit your database server dies. A transaction may fail if it doesn't receive commit .
Hopefully it helps!
Consider a transaction T1,
Start transaction;
Update emp set emp_id=1 where emp_id=3;
commit;
The engine i am using is INNODB engine.
Before commit operation of the above shown transaction, I had accessed the table again it is showing the previous committed values. If the Row Level locking is placed on the table, it might have shown the error (you cannot access while some transaction is in the middle). Is there any wrong in my understanding.? Can any one help me on this?
Anything that is done as a part of a transaction is available to the same transaction even before the transaction is committed. The changes are not available in other transactions.
To test this, you need to update in one transaction and then from another terminal start a new transaction and try to access. The second transaction will be able to read the data but if you try to update the update will block and wait for the first transaction to be committed.
If you want the second select to wait and return the updated data you should use select for update.
I have a long-running script that may or may not have an uncomitted transaction at the end. I would like to have something at the bottom to just clean up and if there is a transaction hanging out somewhere, just commit it, and if there is one another level up, commit that one, etc.
How can I do that?
Thanks!
Loop until all commuted. Strange situation to be in though...
WHILE XACT_STATE() = 1
COMMIT TRAN