In the php script if my query is incorrect, exit the program with a die.
My question is, if they are in the middle of a transaction, that it will end? Will run an implicit ROLLBACK?
mysql_query('BEGIN'); mysql_query('UPDATE ...'); mysql_close();
in this case behaves like mysql? and using persistent connections? (http://www.php.net/manual/en/function.mysql-pconnect.php#33994)
The MySQL engine will rollback transactions when errors occur, or if the session closes for any reason before commit. Only committed transactions are persisted. See the transaction documentation for more details.
It's depend on how you are performing transaction from PHP side.
If you are using simple mysql_query function to run each transaction statement separately and if any query fails the transaction never rollback.
If you are creating transaction in stored procedure and calling that stored procedure from PHP. The changes will be rolled back if any query fails in transaction.
if your QUERY is wrong and not executed then nothing will be changed in your tables..dont worry
Related
I am experiencing odd behavior when attempting to NOT auto commit inserts or updates in my php project using the oci_* functions.
According to the documentation the insert and update queries should not be committed when the script ends, unless the oci_commit function is called:
Using OCI_NO_AUTO_COMMIT mode starts or continues a transaction. Transactions are automatically rolled back when the connection is closed, or when the script ends. Explicitly call oci_commit() to commit a transaction, or oci_rollback() to abort it.
When inserting or updating data, using transactions is recommended for relational data consistency and for performance reasons.
If OCI_NO_AUTO_COMMIT mode is used for any statement including queries, and oci_commit() or oci_rollback() is not subsequently called, then OCI8 will perform a rollback at the end of the script even if no data was changed. To avoid an unnecessary rollback, many scripts do not use OCI_NO_AUTO_COMMIT mode for queries or PL/SQL. Be careful to ensure the appropriate transactional consistency for the application when using oci_execute() with different modes in the same script.
When I perform an INSERT query with OCI_NO_AUTO_COMMIT as second parameter in the oci_execute function, and afterwards call the oci_rollback function before the script ends, the data is not committed - as expected. But, if I do the same procedure and do not call the oci_rollback function (neither the oci_commit function) before the script ends, the data is committed. What am I missing? Am I misunderstanding the documentation?
The following code commits the insert, which is not what I expect.
$sqlString = "INSERT INTO table1 (col1) VALUES ('test')";
$stid = oci_parse($dbConnection, $sqlString);
$r = oci_execute($stid, OCI_NO_AUTO_COMMIT);
NOTE: The project is running PHP7 and OCI8.
Check you are not executing a subsequent DDL statement (such as CREATE TABLE) since that will trigger a commit by the database.
I had a similar problem while calling procedures (I wanted to wait for all of them to be successful to commit, and if not rollback all of them).
The problem was that some people add a COMMIT; statement at the end of procedures, I had to remove it for it to work.
When doing 1 or more stored procedures, can you place a transaction around the procedure instead of inside of it?
$db->beginTransaction();
$db->exec("call my_procedure()");
$db->exec("call my_second_procedure()");
$db->commit();
When doing the above (pdo), does the transaction commit after both calls, or does it auto commit after each call is run making beginTransaction() and commit() useless?
Yes, you can.
As long as none of the procedures executes a COMMIT or ROLLBACK or START TRANSACTION internally, and as long as none of the procedures (or your code) executes any of the statements that cause an implicit commit, this works fine.
Autocommit is not in effect while you have a transaction running, even though SELECT ##autocommit; will still indicate "1," which is only an indication that your session is in autocommit mode when a transaction isn't active.
I would say, "it depends" :-)
first of all, if you are using MyISAM, which does not support transaction, PDO::beginTransaction() still returns true, but no transaction started.
See http://php.net/manual/en/pdo.transactions.php
I'm using PHP's mysqli library. Database inserts and updates are always in a try-catch block. Success of each query is checked immediately (if $result === false), and any failure throws an exception. The catch calls mysqli_rollback() and exits with a message for the user.
My question is, should I bother checking the return value of mysqli_rollback()? If so, and rollback fails, what actions should the code take?
I have a hard time understanding how a rollback could fail (barring some atrocious bug in MySQL). And since PHP is going to exit anyway, calling rollback almost seems superfluous. I certainly think it should be in the code for clarity, but when PHP exits it will close the connection to MySQL and uncommitted transactions are rolled back automatically.
if rollback fails (connection failure for example), the changes will be rollbacked after the connection close anyway, so you don't need to handle the error. When you are in transaction, unless you have explicit commit (or you are running in autocommit mode, which means you have commit after each statement), the transaction is being roll back.
If a session that has autocommit disabled ends without explicitly
committing the final transaction, MySQL rolls back that transaction.
The only case you would like to handle rollback error is if you are not exiting from your script, but starting a new transaction later, as starting transaction will implicitly commit the current one. Check out Statements That Cause an Implicit Commit
mysqli_rollback can fail if you're not (never were) connected to the database. Depends on your error-handling before-hand.
I have just successfully attempted using beginTransaction() to execute my sql statements in my project using PHP. I have an array of items need to be written to the database, and each item must be validated against something before getting stored. One of the good things about turning off the auto-commit behaviour of a database is you can rollback the whole transaction if something goes wrong in the middle. In my project, if one item is invalid, the whole array should not be recorded in the database, which is why I chose to use this approach.
Now I am just wondering if this really is a better way in terms of performance? Because even if the last item in the array is validated, I still need to manually commit() the previous execution. Does commit repeat the sql execution?
The only advantage I can think of right now is you only need to do one loop instead of two if you want to validate them all (assuming all items are valid) and then write each of them.
First validate everything, then begin a transaction, database interaction. Transactions are not made to help validating the data.
Commit does not repeat SQL execution.
Typically, when working in a transactional, whenever you execute an INSERT/UPDATE/DELETE statement, the database takes a copy of the records/data pages to a transaction log, and then executes the actual record changes.
If anybody else tries to access those records/data pages during the course of your transaction, they will be redirected to the copy in the transaction log.
Then, when you execute the commit, the data in the database itself is already updated, and all the server needs to do is delete the transaction log.
If you rollback rather than commit, then the database server backtracks through the transaction log, restoring all the records/data pages that you have updated to their original state, deleting each transaction log entry as it goes.
Therefore, a rollback is an overhead, because the database server has to restore the data to its pre-transaction state.
You can use savepoints. From the manual:
BEGIN;
INSERT INTO table1 VALUES (1);
SAVEPOINT my_savepoint;
INSERT INTO table1 VALUES (2);
ROLLBACK TO SAVEPOINT my_savepoint;
INSERT INTO table1 VALUES (3);
COMMIT;
You still have to validate your input, but you can now rollback within a single transaction. Using transactions can make the database faster because there are less (implicit) commits.
If I run the following PHP, I would expect no value to be inserted into the test table, because I have a transaction that I haven't committed:
$db = mysql_connect("localhost","test","test");
mysql_select_db("test");
mysql_query("begin transaction;");
mysql_query("insert into Test values (1);") or die("insert error: ". mysql_errror());
die('Data should not be commited\n');
mysql_query("commit;"); // never occurs because of the die()
But instead it seems to commit anyway. Is there a way to turn off this behaviour without turning off autocommit for the PHP that doesn't use transactions elsewhere on the site?
Use mysql_query('BEGIN'). The SQL "BEGIN TRANSACTION" is not valid (and in fact mysql_query is returning false on that query, which means there is an error). It's not working because you never start a transaction.
The syntax to start a transaction is:
START TRANSACTION
The feature you are talking about is AUTOCOMMIT. If you don't want it, you'll have to disable it:
SET autocommit = 0
The reference can be found at http://dev.mysql.com/doc/refman/5.1/en/commit.html
I also recommend that you test the return value of all mysql_...() functions. You cannot assume that they'll always run successfully.
By default, the transaction will not be rolled back. It is the responsibility of your application code to decide how to handle this error, whether that's trying again, or rolling back.
If you want automatic rollback, that is also explained in the manual:
The current transaction is not rolled back. To have the entire transaction roll back, start the server with the `--innodb_rollback_on_timeout` option.