How can I implement commit/rollback for MySQL in PHP? - php

Well basically I have this script that takes a long time to execute and occasionally times out and leaves semi-complete data floating around my database. (Yes I know in a perfect world I would fix THAT instead of implementing commits and rollbacks but I am forced to not do that)
Here is my basic code (dumbed down for simplicity):
$database = new PDO("mysql:host=host;dbname=mysql_db","username","password");
while (notDone())
{
$add_row = $database->prepare("INSERT INTO table (columns) VALUES (?)");
$add_row->execute(array('values'));
//PROCESSING STUFF THAT TAKES A LONG TIME GOES HERE
}
$database = null;
So my problem is that if that if the entire process within that while loop isn't complete then I don't want the row inserted to remain there. I think that somehow I could use commits/rollbacks at the beginning and end of the while loop to do this but don't know how.

Take a look at this tutorial on transactions with PDO.
Basically wrap the long running code in:
$dbh->beginTransaction();
...
$dbh->commit();
And according to this PDO document page:
"When the script ends or when a connection is about to be closed, if you have an outstanding transaction, PDO will automatically roll it back. "
So you will lose the transaction that was pending when the script timed out.
But really, you ought to redesign this so that it doesn't depend on the scriipt staying alive.

You need to use InnoDB based tables for transactions then use any library like PDO or MySQLi that supports them.

try
{
$mysqli->autocommit(FALSE);
$mysqli->query("insert into tblbook (id,cid,book) values('','3','book3.1')");
echo $q_ins=$mysqli->affected_rows."<br>";
$mysqli->query("update tblbook set book='book3' where cid='3'");
echo $q_upd=$mysqli->affected_rows."<br>";
$mysqli->commit();
}
catch(PDOException $e)
{
$mysqli->rollback();
echo $sql . '<br />' . $e->getMessage();
}

<?php
//This may help someone....This code commit the transactions
//only if both queries insert and update successfully runs
$mysqli=new mysqli("localhost","user_name","password","db_name");
if(mysqli_connect_errno())
{
echo "Connection failed: ".mysqli_connect_error();
}
else
{
$mysqli->autocommit(FALSE);
$mysqli->query("insert into tblbook (id,cid,book) values('','3','book3.1')");
echo $q_ins=$mysqli->affected_rows."<br>";
$mysqli->query("update tblbook set book='book3' where cid='3'");
echo $q_upd=$mysqli->affected_rows."<br>";
if($q_ins==1 && $q_upd==1)
{
$mysqli->commit();
echo "Commit<br>";
}
else
{
$mysqli->rollback();
echo "Rollback<br>";
}
}
?>

Related

PHP Prepared Statement not inserting, no errors appearing

I am attempting to insert some data via prepared statements in PHP. I have the following code which is not inserting for me. I also have the following code set already
ini_set('display_errors', 1);
error_reporting(~0);
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
$sqlInsert = "INSERT INTO deck_cards (deckid, cardid, qty) VALUES (?,?,?)";
$stmtInsert = $conn->prepare($sqlInsert);
if ($stmtInsert)
{
$stmtInsert->bind_param("sss", $deckid, $cardid, $cardcount) or trigger_error($stmtInsert->error, E_USER_ERROR);
$stmtInsert->execute() or trigger_error($stmtInsert->error, E_USER_ERROR);
echo "Check if this ran";
}
else {
echo "Error: " . $sql . "<br>" . $conn->error;
$conn->close();
}
$stmtInsert->close();
}
catch (Exception $ex)
{
echo 'Exception occurred '.$ex->getTraceAsString();
}
When this executes, I do see the text "Check if this ran" but no other messages. The data is not inserted into the database. Additionally, I echo'd the sql string and variables and ran it against the MySQL directly and it inserted ok. Not sure what is happening in my very straightforward code above.
Additionally, inserts are happening ok in other pages within my app, but this page for some reason isn't working.
I know it's overkill on my error reporting, but I threw everything I could think of to see if there is an error somewhere, but this one is a head scratcher for me. Thanks for any assistance!

RollBack () and beginTransaction() not work in my PHP PDO

RollBack () and beginTransaction() not work in my PHP PDO and my table type is innoDB. In the following code my $sql1 is correct and my $sql2 is wrong (I added d to $last_id to just make it wrong). But it still executes sql1 meaning roll back no effect. Thank you for your advice.
<?php
include 'connect.php';
// Get multiple input field's value
try {
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Starts our transaction
$conn->beginTransaction();
foreach ($_POST['phone'] as $value) {
$sql1 = "INSERT INTO tbl_contact_info (type)
VALUES ('$value')";
// use exec() because no results are returned
$conn->exec($sql1);
$last_id = $conn->lastInsertId();
$sql2="INSERT INTO tbl_img (img_type)
VALUES ('$dlast_id')";
$conn->exec($sql2);
}
// Commits out queries
$conn->commit();
echo "New record created successfully";
}
catch(PDOException $e)
{
// Something borked, undo the queries!!
$conn->rollBack();
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
?>
First of all (and sorry it it's obvious but I realised it's not always clear to everyone) SQL and PHP are different languages. MySQL Server will not react to Undefined variable notices triggered in PHP code.
Secondly, notices are not exceptions so they cannot be caught with try/catch statements. (You can certainly write a custom error handler that will throw exceptions on errors but it doesn't seem to be the case here.)

Attempting to insert new row into database using PDO

Ok, so I've been trying to do this for days, and I've been reading all sorts of tutorials, but I seem to be missing something, because I still can't get it. I'm working on learning about web forms and inserting the form input into the respective database. I'm able to take the info from the form and echo it on the result page, so I know that all works. but I can't seem to get the form input to go into my database. I know the connection works, so there must be something wrong with my syntax.
PHP
//DB Configs
$username = null;
$password = null;
try {
$db = new PDO("mysql:host=localhost;dbname=Testing3", $username, $password);
//Set the PDO error mode to exception (what does this mean?)
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//Prepare SQL and bind parameters
$sql = $db->prepare("INSERT INTO `NFK_SPECIES` (`Name`)
VALUES (:name)");
//Insert a Row
$species = $_POST['Species'];
$sql->execute(array(':name'=>$species));
}
catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
$result = $db->query('SELECT * from `NFK_Species` ORDER BY `Id` DESC');
//Query
/*
$input = $db->query("INSERT INTO `NFK_Species` (`Id`, `Name`) VALUES (Null, `$species`)");
$result = $db->query('SELECT * from `NFK_Species` ORDER BY `Id` DESC');*/
//Kill Connection
$db = Null;
}
HTML/PHP (web page)
<h1>Inserting a New Species into Database:</h1>
<h3>Results</h3>
<?php
if ($sql->execute()){
echo "Data input was successful";
while ($rows = $result->fetch()){
echo $rows['Name']; echo ", ";
}
} else {
echo "Data input failed."; echo mysql_error();
}
?>
This is only my current attempt at doing this. I prefer the attempt I had before, with the bindParam and simple execute(), so if I could get that to work instead, I'd appreciate it. The following example also has the Id column for this table. This is an auto-increment column, which I read doesn't need to be included, so I excluded it from my recent attempt. Is that correct?
Past PHP
//Prepare SQL and bind parameters
$sql = $db->prepare("INSERT INTO `NFK_SPECIES` (`Id`, `Name`)
VALUES (Null, :name)");
$sql->bindParam(':name', $species);
//Insert a Row
$species = $_POST['Species'];
$sql->execute();
I've been reading a bunch of tutorials (or trying to), including attempting to decipher the php.net tutorials, but they all seem to be written for people who already have a good handle on this and experience with what's going on, and I'm very new to all of this.
Alright, I was able to figure out my problem, and then successfully insert a row using my code.
Debugging:
So the code posted above was breaking my code, meaning my page wouldn't load. I figured that meant that there was a syntax error somewhere, but I couldn't find it, and no one else had located it yet. Also, that meant that my Error Alerts weren't working to let me know what the problem was. If you look at my original PHP sample, you'll see down at the very bottom there is a single "}" just hanging out and serving no purpose, but more importantly, it's breaking the code (stupid, hyper-sensitive php code). So I got rid of that, and then my Error messages started working. It said I couldn't connect to my database. So I look over my database login syntax, which looked fine, and then you'll notice in my 1st php sample that somehow I'd managed to set my $username and $password to NULL. Clearly that isn't correct. So I fixed that, and next time I refreshed my page, I'd successfully entered a row in my database! (yay)
Note:
In my original php sample, I'd included the Id Column, which is auto-incremented, for the row insertion, with a value of NULL. This worked, and it inserted the row. Then I experimented with leaving it out altogether, and it still worked. So the updated working code below doesn't include the Species Id.
Working code:
<body>
<h1>Inserting a New Species into Database:</h1>
<h3>Results</h3>
<?php
//DB Configs
$username = root;
$password = root;
try {
//Connect to Database
$db = new PDO("mysql:host=localhost;dbname=Testing3", $username, $password);
//Enable PDO Error Alerts
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//Prepare SQL statement and bind parameters
$sql = $db->prepare("INSERT INTO `NFK_SPECIES` (`Name`) VALUES (:name)");
$sql->bindParam(':name', $species);
//Insert a Row
$species = $_POST['Species'];
$sql->execute();
// Echo Successful attempt
echo "<p class='works'><b>" . $species . "</b> successfully added to database.</p></br></br>";
}
catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
// Gather updated table data
$result = $db->query('SELECT * from `NFK_Species` ORDER BY `Id` DESC');
//Kill Connection
$db = Null;
while ($rows=$result->fetch()){
echo $rows['Id']; echo " - "; echo $rows['Name']; echo "</br>";
}
?>
<body>

Waiting for task in PHP to finish before moving to next item

Quick question here, i've got a process running that grabs RSS feeds and adds them to a mySQL database.
During this process I'll be using the Readability API to grab the URL content as I go.
Now this works fine on single entries, but as this script can have hundreds of entries, nothing is being inserting into my database.
I'm wondering if it's not getting a chance to finish the process and immediately skipping onto the next entry in the RSS.
Can anyone suggest a way of letting it finish before moving on? Code below:
$db_hostname="localhost";
$db_username="myusername";
$db_password="mypassword";
try
{
/* query the database */
$db = mysql_connect($db_hostname,$db_username,$db_password);
if (!$db)
{
die("Could not connect: " . mysql_error());
}
mysql_select_db("MyDB", $db);
// Get stories that don't have a the readability assigned
$query="select item_id, item_url from tw_articles_parse where story_readability = '' LIMIT 0 , 1";
$result=mysql_query($query);
$num=mysql_numrows($result);
// Close the DB connection
mysql_close();
// Start the loop of source RSS feeds
$i=0;
while ($i < $num) {
$item_url=mysql_result($result,$i,"item_url");
$item_id=mysql_result($result,$i,"item_id");
// Parse the story URL into the Readability API
$url = "https://www.readability.com/api/content/v1/parser?url=$item_url&token=myapikey";
// Get the contents of the JSON returned by the API
$json = file_get_contents($url);
// Decode the JSON
$out = json_decode($json, true);
// Set the content as a variable
$story = mysql_real_escape_string($out['content']);
// Insert into the DB - Adding 0 to story_club_id as default
$item_insert_sql = "UPDATE tw_articles_parse SET story_readability=$story WHERE item_id='" . $item_id . "'";
$insert_item = mysql_query($item_insert_sql, $db);
$i++;
}// end the loop of feeds
} catch (Exception $e)
{
echo 'Caught exception: ', $e->getMessage(), "\n";
}
Probably nothing is inserted because you are using UPDATE statement and there are simply no such records with correspoding item_id to be updated?
Try changing UPDATE query to INSERT ... ON DUPLICATE KEY UPDATE
Unfortunately we don't know your database scheme, but something like this should work:
$item_insert_sql = "INSERT INTO tw_articles_parse (story_readability, item_id) VALUES ('$story', $item_id) ON DUPLICATE KEY UPDATE story_readability='$story'";
Maybe you're running out of memory or time? Enable warnings and error reporting:
ini_set("display_errors", 1);
error_reporting(E_ALL);

Executing multiple update statements in PHP

I have three update statements to be executed in PHP, i am getting the values of all these as return parameters. How to execute each statement independely and finally show the end user the result that it has been successfully updated.
<?php
public function name($parameter1,$parameter2.... $parametern) {
}
?>
Then how finally we can get the result in my row object.
Ah i think i see, well looks to me from your update statements that you want to update 3 different tables which all depend on 'tycodashboard'.
In that case i advise you use transactions to retain a bit of data integrity, otherwise say if one fails? you'll have lost some data. As a general rule, if you need to do more than 1 update simultaneously use transactions.
Heres a great article on the subject: http://dev.mysql.com/doc/refman/5.0/en/commit.html
Its quite easy to do, just make you sure your tables are using the INNODB, then all you have to do is append START TRANSACTION to the top of your sql script and then COMMIT at the end.
You might be trying to combine too much into a single function, whenever i'm updating multiple tables, it's easier to just handle each one in turn, rather than trying to stuff them all into one return. So try making a function that saves it, returning success or failure, then call it from your main function for each one of your sql scripts passing in the values.
//This is the function that gets called from your page.
public function my_called_function() {
//your sql script (using "" means you can put variables in without having to remove the quotes)
$sql = "UPDATE....SET 'col' = $_POST['myvalue']";
//Run your script and get result
$result = $this->save_my_stuff($sql);
//if not null means success!
if($result) {
echo 'success!'; // your success message
}
else {
echo 'something bad happened'; //your failure message
}
}
//this is the function that does the saving!
private function save_my_stuff($sql_script) {
//Make connection
$conn = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
//Check connection
if(!$conn) {
//connection failed
die('Could not connect: '.mysql_error());
}
//Select your database using your connection object
mysql_select_db(DB_NAME, $conn);
//try and save
try {
//run the query
$result = mysql_query($sql_script, $conn);
//return the result
return mysql_result($result);
}
catch (Exception $e) {
//deal with exception
return null;
}
//close connection
mysql_close();
}

Categories