How to rollback the last executed mysql query.Suppose there are 2-3 queries depend upon submit button and first query run successfully and second failed then how to rollback first query..
Use mysql_rollback or mysqli_rollback depending on whether you are using mysql or mysqli extension
This link should give you a clearer idea
http://www.w3schools.com/php/func_mysqli_rollback.asp
You need to use transactions.
Sequence will be :
1) Begin the transaction
2) Issue one or more SQL commands
3) See if there is any error or not
4) If there is error then issue ROLLBACK if not COMMIT
Note : By default, MySQL runs with autocommit mode enabled. This means that as soon as you execute a statement that updates (modifies) a table, MySQL stores the update on disk to make it permanent.
To disable autocommit mode implicitly for a single series of statements, use the START TRANSACTION statement which will make autocommit disabled until you end the transaction with COMMIT or ROLLBACK.
Refer this
Use transactions:
START TRANSACTION;
SELECT * FROM tbl_foo;
SELECT * FROM llsldllfdlfdld; -- typo, fails!
ROLLBACK; -- reverses first transaction
If everything works, instead of ROLLBACK, send COMMIT; to make the changes final.
Related
With regards to using PHP's API for MySQL transaction support I was wondering about autocommit.
For example, I'm not sure how it works by default, but ideally I would like all queries to auto commit unless I explicitly start a transaction with something like:
$db->begin_transaction();
$db->query(...);
$db->query(...);
$db->commit();
As a related question, I notice begin_transaction() wasn't introduced until PHP 5.5 so is it possible to get behaviour before 5.5?
I know there is $db->autocommit() but does that mean if I want the above behaviour I would need to have it on by default and then do $db->autocommit(false) before any transactions and then $db->autocommit(true) afterwards?
Here's the documentation on transactions and the autocommit setting.
To quote from that documentation:
By default, MySQL runs with autocommit mode enabled. This means that as soon as you execute a statement that updates (modifies) a table, MySQL stores the update on disk to make it permanent. The change cannot be rolled back.
As I read this, the way it works is this:
Imagine you're making queries without using transactions. You do an INSERT with autocommit on and that INSERT happens immediately (ie. is stored to disk right away). An UPDATE? It happens immediately.
Now imagine you turn off autocommit and make queries the same way. The quote above implies that if you perform that INSERT command with autocommit off, it is not immediately stored to disk. So what happens to that INSERT? To quote from the documentation again:
After disabling autocommit mode by setting the autocommit variable to zero, changes to transaction-safe tables (such as those for InnoDB or NDBCLUSTER) are not made permanent immediately. You must use COMMIT to store your changes to disk or ROLLBACK to ignore the changes.
So, in short, using autocommit is a different way of implementing transactions. In MySQL you can do this:
START TRANSACTION;
INSERT INTO table VALUES (1, 2, 3);
COMMIT;
or you can do this:
SET autocommit=0;
INSERT INTO table VALUES (1, 2, 3);
COMMIT;
Note too that there's an implicit commit when you change the autocommit value - so doing this would be equivalent:
SET autocommit=0;
INSERT INTO table VALUES (1, 2, 3);
SET autocommit=1;
You can do things the same way in PHP, using either $db->begin_transaction(); or $db->autocommit(false); to start the transaction, the doing $db->commit(); at the end. Personally, I find the begin_transaction method clearer.
I have a system that handles many queries per second. I code my system with mysql and PHP.
My problem is mysqli transaction still commit the transaction even the record is deleted by other user at the same time , all my table are using InnoDB.
This is how I code my transaction with mysqli:
mysqli_autocommit($dbc,FALSE);
$all_query_ok=true;
$q="INSERT INTO Transaction() VALUES()";
mysqli_query ($dbc,$q)?null:$all_query_ok=false;
$q="INSERT INTO Statement() VALUES()";
mysqli_query ($dbc,$q)?null:$all_query_ok=false;
if($all_query_ok==true){
//all success
mysqli_commit($dbc);
}else{
//one of it failed , rollback everything.
mysqli_rollback($dbc);
}
Below are the query performed at the same time in other script by another user and then end up messing the expected system behaviour,
$q="DELETE FROM Transaction...";
mysqli_query ($dbc,$q)?null:$all_query_ok=false;
Please advice , did I implement the transaction wrongly? I have read about row-level locking and believe that innoDB does lock the record during a transaction
I don't know which kind of transactions you're talking about but with the mysqli extension I use the following methods to work with transactions:
mysqli::begin_transaction
mysqli::commit
mysqli::rollback
Then the process is like:
Starting a new transaction with mysqli::begin_transaction
Execute your SQL queries
On success use mysqli::commit to confirm changes done by your queries in step 2 OR on error during execution of your queries in step 2 use mysqli::rollback to revert changes done by them.
You can think of transactions like a temporary cache for your queries. It's someway similar to output caching in PHP with ob_* functions. As long as you didn't have flushed the cached data, nothing happens on screen. Same with transactions: as long as you didn't have commited anything (and autocommit is turned off) nothing happens in the database.
I did some research on row level locking which can lock record from delete or update
FOR UPDATE
Official Documentation
Right after the begin transaction I have to select those record I wanted to lock like below
SELECT * FROM Transaction WHERE id=1 FOR UPDATE
So that the record will be lock until transaction end.
This method doesn't work on MyISAM type table
Looks like a typical example of race condition. You execute two concurrent scripts modifying data in parallel. Probably your first script successfully inserts records and commits the transaction, and the second script successfully deletes records afterwards. I'm not sure what you mean by "the query performed at the same time in other script by other user" though.
You will have to do this this way:
mysqli_autocommit($dbc,FALSE);
$dbc->begin_transaction();
$all_query_ok=true;
$q="INSERT INTO Transaction() VALUES()";
mysqli_query ($dbc,$q)?null:$all_query_ok=false;
$q="INSERT INTO Statement() VALUES()";
mysqli_query ($dbc,$q)?null:$all_query_ok=false;
if($all_query_ok==true){
//all success
mysqli_commit($dbc);
}else{
//one of it failed , rollback everything.
mysqli_rollback($dbc);
}
you can use the object oriented or the procedural style when calling begin_transaction (I prefer the object oriented).
I am using InnoDB in MySQL and accessing the table from PHP with PDO.
I need to lock the table, do a select and then, depending on the result of that either insert a row or not. Since I want to have the table locked for as short a time as possible, can I do it like this?
prepare select
prepare insert
begin transaction
lock table
execute select
if reservation time is available then execute insert
unlock table
commit
Or do the prepares have to be inside the transaction? Or do they have to be after the lock?
Should the transaction only include the insert, or does that make any difference?
beginTransaction turns off autocommit mode, so it only affects queries that actually commit changes. This means that prepared statements, SELECT, and even LOCK TABLES are not affected by transactions at all. In fact, if you're only doing a single INSERT there's no need to even use a transaction; you would only need to use them if you wanted to do multiple write queries atomically.
I have a very extensive PHP update script based on PHP/Yii that updates a database on different database types (MSSQL, Postgres and MySQL).
The whole script runs within a transaction. However there are some statements that lead to a query error (for example if a certain key already exists on a table). I surrounded these with try/catch statements - this works fine so far in MySQL
However on Postgres once an invalid query was issued the transaction is automatically failing. The following error message is shown for all following statements:
CDbCommand failed to execute the SQL statement: SQLSTATE[25P02]: In failed sql transaction: ERROR: current transaction is aborted, commands ignored until end of transaction block
But what I need is Postgres to continue the transaction because I want to decide in the application when to roll back - or some way to clear out the error and continue the transaction.
How to do that?
Use a savepoint for that purpose:
BEGIN; -- transaction starts here
-- do things if you want
SAVEPOINT my_savepoint;
-- failing statement here
-- all other statements are ignored
ROLLBACK TO SAVEPOINT my_savepoint;
-- continue your transaction starting from my_savepoint
COMMIT;
I'm curios if this can be achieved as I'm currently facing a bug and would like to see if putting a SELECT and an UPDATE in a transaction would fix it (if you're wondering why I'm not posting the code that causes the bug it's because it's a complex environment and I can't post all the influencing factors).
Something that I'm also interested in, related to this, is if you have ever experienced code that had and UPDATE query written after a SELECT query, yet the UPDATE gets executed before the SELECT (with the possibility that the script might run twice ruled out).
It depends on what do you mean by a transaction.
There are two types of transactions:
Implicit transactons: as in INSERT, UPDATE, SELECT, DELETE statements, and in such statements there is no explicit transaction commands, and the database engine will rollback the whole statement if an error happens.
Explicit Transactions: in such the enclosed statements inside the transaction are executed as a unit and either COMMIT the whole transaction or ROLLBACK .
So you can't have both SELECT and UPDATE inside one query, but you can but them inside a transaction like:
START TRANSACTION;
SELECT * FROM tableName;
UPDATE table SET something = 'other something' WHERE thirdsomething = #s;
COMMIT;
Then Put them in a stored procedure or a UDF.
Note that: SELECT statements do not modify data, so you might not need to enclose it in a transaction, so in your case you will have only UPDATE statement you can just use a stored procedure without a transaction.