SQL transaction not working when initiated via PHP - php

I have the following query which does not work when it is initiated by my PHP code:
$sql = 'START TRANSACTION;
DELETE FROM task_actions
WHERE task_id='.$id.';
DELETE FROM tasks
WHERE id='.$id.';
COMMIT;
';
When I echo $sql and put the output directly into phpMyAdmin, it works without a problem; and when I had it done in two steps instead of one transaction, it worked from my PHP code, too.
I first thought MySQL might not allow transactions, but stackoverflow.com/questions/2050310 and stackoverflow.com/questions/2960012 showed that was wrong.
I found I could disable autocommit, do both queries and reactivate autocommit (stackoverflow.com/a/17607619 & stackoverflow.com/a/12092151), but I would prefer not to.
Any ideas why it does not work?

$sql = 'START TRANSACTION';
// run this query
$sql = 'DELETE FROM task_actions WHERE task_id=?';
// run this query
$sql = 'DELETE FROM tasks WHERE id=?';
// run this query
$sql = 'COMMIT';
// finally run this one

Related

php mysql atomic ' Select and Delete ' on a Table

I have an script of a queue like situation which each user can post a request which is added to the queue and others can accept these requests by the order of that queue but each request should only be accepted by one user .
but if I implement it with two queries one for the select other for the delete
something Like this
<?php
$sql = "SELECT id,CreationDate FROM `RandomQueue` order by CreationDate limit 1 ;";
$result = $conn->query($sql);
if ($result->num_rows == 1) {
$row = $result->fetch_assoc();
echo "this request is accepted".$row['id'];
$sqlDel = "DELETE FROM `RandomQueue` WHERE id = {$row['id']}";
$conn->query($sql);
}
?>
it would not work because many problems may occur like two user accepting one request and so on..(mutex problem) is it possible to achieve this by one sql query(to make it atomic)? and if not then any suggestion on how to implementing this logic would be nice ,thanks a lot;
Atomicity is one of the database transaction properties (ACID), so you need make sure your database engine support transaction.
In MySQL, MyISAM doesn't support transaction and you must use InnoDB.
If you are using InnoDB, there are two ways to start database transaction for MySQL in PHP
/* Begin a transaction, turning off autocommit */
$dbh->beginTransaction();
// your business logic goes here
$dbh->commit();
or
$mysqli->begin_transaction(MYSQLI_TRANS_START_READ_ONLY);
// your business logic goes here
$mysqli->commit();

Why I am getting the Error "Commands out of sync; you can't run this command now"

The Documentation of the Error Mentioned in the Title Says
If you get Commands out of sync; you can't run this command now in
your client code, you are calling client functions in the wrong order.
This can happen, for example, if you are using mysql_use_result() and
try to execute a new query before you have called mysql_free_result().
It can also happen if you try to execute two queries that return data
without calling mysql_use_result() or mysql_store_result() in between.
From here: http://dev.mysql.com/doc/refman/5.0/en/commands-out-of-sync.html
But In First Query I am not fetching any data from mysql database, I am just inserting. And In second Query I am getting the data from database.
Here is My code
$connection = mysqli_connect("localhost","username","password","tbl_msgs");
if(mysqli_connect_errno($connection))
{
die("Failed to connect to MySQL: " . mysqli_connect_error());
}
$query = "INSERT INTO users (total_comments, total_views)
VALUES ({$total_comments}, {$total_views});";
$query .= "INSERT INTO msgs (notifications) VALUES ({$notifications})";
mysqli_multi_query($connection,$query);
Upto this Step every thing is fine. But When I execute the following query It gives the Error
$select_query = "SELECT * FROM msgs WHERE msg_id = {$msg_id}";
$result_set = mysqli_query($connection,$select_query);
if(!$result_set) {
die(mysqli_error($connection));
}
Here it gives the Error Commands out of sync; you can't run this command now. I can't understand this situation
Note: There is any Problem in the Query, I have executed the same query directly to PHPMyAdmin and it works fine.
There are result set pending from the query:
mysqli_multi_query($connection,$query);
You need to use/store result before you can proceed with next query after:
Since you look like you don't really care about the first result set, do this after the multi query..
do
{
$result = mysqli_store_result($connection);
mysqli_free_result($result);
}while(mysqli_next_result());
Another alternative is to close the connection and starts it again..
mysqli_close($connection);
$connection = mysqli_connect("localhost","username","password","tbl_msgs");
It all depends on your requirements.

oracle php lock record

I have this problem.. i am trying to use the lock record for the update. I am using php, and i use oracle as the database. i didnt understand fully but i have managed to copy the previous developer code and make it working.
It is using the odbc_exec(), odbc_fetch_row(). I think that this is suppose to be use for microsoft access data base. But i don't know. And i am also using jquery to fetch this php file(using jquery post) and append to the current page.
But now my senior request me to make sure that if a person is editing one record. then the other cant edit it anymore. They said that something about not closing the connection. can php not close connection to database after 1 page is loaded (when it is using jquery to get the page like mine does)? from what i know, if a page is loaded. the connection to the database is closed.
I want to try this code but i am afraid if i am wrong and the connection would hang.
Now my sql is like this for select all company.
$sqlStr ="select * from company";
$rs = odbc_exec($GblConnOra , $sqlStr);
while (odbc_fetch_row($rs)){
$company_name=odbc_result($rs,"company_name");
$company_id=odbc_result($rs,"company_id");
}
And for select the company to edit
$sqlStr ="select * from company where company_id='34'";
$rs = odbc_exec($GblConnOra , $sqlStr);
while (odbc_fetch_row($rs)){
$company_name=odbc_result($rs,"company_name");
}
The updating
$sqlStr ="update compay set company_name=? where company_id=?";
$stmt = odbc_prepare($GblConnOra , $sqlStr);
$res = odbc_execute($stmt, array($company_name, $company_id));
i think the sql will be like this. to lock the record.
$sqlStr ="select * from company for update skip locked";
$rs = odbc_exec($GblConnOra , $sqlStr);
while (odbc_fetch_row($rs)){
$company_name=odbc_result($rs,"company_name");
$company_id=odbc_result($rs,"company_id");
}
can i do this?
what would my sql be for selecting a row to edit?
what would my sql be for updating the row?
And from my understanding, this lock would be release after an update commit or rollback is call.

Transactions MySql and php

I'm confused abt running transactions through php script.
In my MySql autocommit is set to 1,
yet when I run a script
ex: mysql_query("START TRANSACTION");
$sql="INSERT INTO
`address`(`Address_Id`,
`Address_Line1`,
`Address_line2`,
`Zip`,
`Created_By`,
`Created_Date`,
`Updated_By`,
`Updated_Date`)
VALUES ('2','this is test1','test2','210','SYSTEM','NOW()','SYSTEM','NOW()')";
mysql_query($sql);
When I don't give commit, inserted records in the table is zero.
the record comes up only if I give commit command.
Also please tell me what happens if in a php script I start transaction and then dont give either roll back or commit statements
http://dev.mysql.com/doc/refman/5.5/en/commit.html:
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.
But if you specify START TRANSACTION explicitly - then it isn't taken into account, so you work in a transaction that should be committed.
Try to do like this.
mysql_query("BEGIN");
$query="";
$result=mysql_query($query);
if($result==0)
{
mysql_query("ROLLBACK");
echo $error_message;
// mysql_query($query_setId);
die();
}
mysql_query("COMMIT");

Running multiple queries with mysqli_multi_query and transactions

I'm developing an update system for a Web Application written in PHP. In the process of the update I might need to execute a bunch of MySQL scripts.
The basic process to run the scripts is:
Search for the Mysql scripts
Begin a transaction
Execute each script with mysqli_multi_query since a script can contain multiple queries
If everything goes ok COMMIT the transaction, otherwise ROLLBACK.
My code looks something like:
$link = mysqli_connect(...);
mysqli_autocommit($link, false);
// open dir and search for scripts in file.
// $file is an array with all the scripts
foreach ($scripts as $file) {
$script = trim(file_get_contents($scriptname));
if (mysqli_multi_query($link, $script)) {
while (mysqli_next_result($link)) {
if ($resSet = mysqli_store_result($link)) { mysqli_free_result($resSet); }
if (mysqli_more_results($link)) { }
}
}
// check for errors in any query of any script
if (mysqli_error($link)) {
mysqli_rollback($link);
return;
}
}
mysqli_commit($link);
Here is an example of the scripts (for demonstration purposes):
script.1.5.0.0.sql:
update `demo` set `alias` = 'test1' where `id` = 1;
update `users` set `alias` = 'user1' where `id` = 1;
script 1.5.1.0.sql:
insert into `users`(id, key, username) values(3, '100', 'column key does not exist');
insert into `users`(id, key, username) values(3, '1', 'column key exists');
In this case, script 1.5.0.0 would execute without errors and script 1.5.1.0 would generate an error (for demonstration purposes, let's say that column key is unique and there is already a row with key = 1).
In this case I want to rollback every query that was executed. But what happens is that the first insert of 1.5.1.0 is not in the database (correctly) but the updates from 1.5.0.0 were executed successfully.
Remarks:
My first option was to split every query from every script with ";" and execute the queries independently. This is not an option since I have to be able to insert HTML code to the database (ex: if I want to insert something like "& nbsp;")
I've already searched StackOverflow and google and came across solutions like this one but I would prefer using a solution like mysqli_multi_query rather than using a function to split every query. It's more understandable and easier for debug purposes
I haven't tested it, but I believe that I could merge all the scripts and execute just a query. However it would be usefull to execute one script at a time so that I can figure out which script has the error.
The tables engine is InnoDB.
Appreciate if you can point some way to make this work.
Edit:mysqli_multi_query() only returns false if the first query fails. If the first query doesn't fail then your code will run mysql_store_result() which if it succeeds will leave mysqli_error() empty. You need to check for errors after every mysqli function that can succeed or fail.
Ok, after spending another day debugging, i've discovered the problem.
Actually, it has nothing to do with the code itself or with mysqli functions. I'm used to MS SQL transactions which supports DDL statements. MySQL does not supports DDL statements and commits data implicitly (Implicit commit). I had one DROP Table in one of the scripts that was auto commiting data.

Categories