Committing transaction outside of stored procedure - php

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

Related

PHP OCI auto committing when using OCI_NO_AUTO_COMMIT in oci_execute

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.

Side-effects of disabling auto-commits

We are trying to run a transaction using the Wordpress wpdb object - not sure if that matters.
wpdb->query('BEGIN TRANSACTION');
// Run transaction related queries
if($error) {
// ROLLBACK
} else {
// COMMIT
}
Now it seems like mysql does this brilliant thing of setting auto_commit to true, which causes every query after execution to auto commit. We learnt that we can disable this amazing feature by running SET auto_commit = 0.
At the end of our query we will be running SET auto_commit = 1. My question is that would this affect any other queries being run on the DB at the same time?
Unfortunately, not every database supports transactions, so PDO needs to run in what is known as "auto-commit" mode when you first open the connection. Auto-commit mode means that every query that you run has its own implicit transaction, if the database supports it, or no transaction if the database doesn't support transactions. If you need a transaction, you must use the PDO::beginTransaction() method to initiate one.
Now guess it is good or bad ?

With PHP and MySQL, should you check for rollback failures?

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.

Transactions not completed

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

In PHP, can I get MySQL to rollback a transaction if I disconnect without committing, rather than commit it?

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.

Categories