I have a PHP script below that I'm running every hour using a cronjob. Sometimes this script runs without any errors and other times it throws a 504 Gateway Timeout.
Can someone please help to improve the execution and efficiency of this script? I believe it can be written cleaner, but not sure where to start.
This is on a shared server and I do not have much control over the settings. Max timeout is 120.
Cronjob:
curl www.mysite.com/apps/script.php
PHP script:
<?php
set_time_limit(500);
$databasehost = "localhost";
$databasename = "foodb";
$databasetable = "footable";
$databaseusername="foouser";
$databasepassword = "foopass";
$fieldseparator = ",";
$lineseparator = "\n";
$csvfile = "inventory.csv";
if(!file_exists($csvfile)) {
die("File not found. Make sure you specified the correct path.");
}
try {
$pdo = new PDO("mysql:host=$databasehost;dbname=$databasename",
$databaseusername, $databasepassword,
array(
PDO::MYSQL_ATTR_LOCAL_INFILE => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
)
);
$sql = "TRUNCATE TABLE $databasetable";
$command = $pdo->prepare($sql);
$command->execute();
echo "Removed records from $databasename.\n<br />";
} catch (PDOException $e) {
die("database connection failed: ".$e->getMessage());
}
$affectedRows = $pdo->exec("
LOAD DATA LOCAL INFILE ".$pdo->quote($csvfile)." INTO TABLE `$databasetable`
FIELDS TERMINATED BY ".$pdo->quote($fieldseparator)."
LINES TERMINATED BY ".$pdo->quote($lineseparator)."IGNORE 1 LINES");
echo "Loaded a total of $affectedRows records from this csv file.\n";
/****/
try {
$pdo = new PDO("mysql:host=$databasehost;dbname=$databasename",
$databaseusername, $databasepassword,
array(
PDO::MYSQL_ATTR_LOCAL_INFILE => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
)
);
$sql = $pdo->exec("
UPDATE wp37_pmxi_posts
JOIN wp37_postmeta USING (post_id)
JOIN inventoryImport ON wp37_pmxi_posts.unique_key = inventoryImport.sku
SET meta_value = inventoryImport.qty
WHERE meta_key = '_stock'");
echo "Updated $affectedRows records after the import.\n";
} catch (PDOException $e) {
die("database connection failed: ".$e->getMessage());
}
?>
Thanks for your time and I appreciate any help.
I had the exact same issue last week and even though I am on a VPS server with a full root access, I didn't want to mess about with the files in the etc/ folder or php.ini or any other PHP settings...
So I came up with my own solution..
Please note this solution and this answer intended to just give you and other people an idea of how you could solve this issue without fiddling with server settings...
The solution was quite simple actually...
First i created an extra column in the MYSQL database with a pre-defined value of 0. You can name it anything you want.
What I did next was basically LIMIT my SELECT to 100.
something like:
SELECT * FROM mytable WHERE newColumn=0 LIMIT 100
And then I did whatever i wanted with this 100 selected items and every time I did that i UPDATE the database and changed the newColumn=1
And I repeated the same process until there is no more data in the MYSQL database with newColumn=0.
once I reach this stage, I UPDATE the table again and reset the newColumn back to 0.
Note that I run the process above on cron job.
This way your PHP won't get killed as you are only selecting 100 rows from the MYSQL.
hope this helps.
Related
I'm trying to get a simple PDO insert to work. I have successfully created a tabled named mydb10 using PDO, and the next part I want to do is insert data into that table. Running the script does not return any errors (PDO error mode exception is enabled), but the table still contains null values.
I'm using a local server to run the PHP file, and am connecting to an Amazon RDS database. Currently all inbound traffic through SSH, HTTP, HTTPS, and MYSQL is allowed through the database's security group
$link = new PDO("mysql:host=$dbhost;dbname=$dbname",$username,$password);
$statement = $link->prepare("INSERT INTO mydb10 (selectedMain, selectedSide)
VALUES(:selectedMain, :selectedSide)");
$statement->execute(array(
"selectedMain" => "test",
"selectedSide" => "test2"
));
This might be silly, but I've been stuck for a while now and any help is appreciated. If you'd like any more information, let me know. I'm trying to utilize PHP in my app, but can't even get this simple test to work, so it's a bit discouraging.
EDIT # 1
This snippet is part of a larger file. I am able to successfully
connect to the database with my credentials and create new tables on the server. I do have PDO error reporting enabled in exception mode, and it has helped me work past syntax errors, but I am no longer getting any errors when I run the code. There are also no errors on the MYSQL server log.
I can provide any additional information that may be useful in debugging if desired.
First you need to properly set connection to MySQL database. You can write this code to sql.php:
<?php
$ServerName = "******";
$Username = "******";
$Password = "******";
$DataBase = "******";
try {
$CONN = new PDO("mysql:host=$ServerName; dbname=$DataBase", $Username, $Password);
$CONN->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$CONN->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
?>
Now, when you properly set connection, you need to execute sql, but before this you need to include sql.php:
try {
$SQL = 'INSERT INTO MyDB10 (SelectedMain, SelectedSide) VALUES(:SelectedMain, :SelectedSide)'; // Write SQL Query to variable
$SQL = $CONN->prepare($SQL); // Prepare SQL Query
$SQL->execute(array('SelectedMain' => 'Test', 'SelectedSide' => 'Test2')); // Execute data to Insert in MySQL Databse
} catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
When you finish all queries you must close connection with:
$CONN = null;
How can I perform a SQLite3 exec at the same time in PHP?
I have this code (by example):
$bd = new SQLite3("database.db");
$bd->busyTimeout(5000);
$bd->exec("INSERT into 'foo' ('data') values ('bar')");
$bd->close();
unset($bd);
And it works, but the real problem is when I connect another computer to my server and I made the insert at the same time (really, I press the key that trigger the code at the same time in both computers) and it show an error "database is locked".
I know that with the pragma WAL the database works in multithread, but it even show the error. Thank you a lot! and sorry for my bad english.
The problem is sqlite3 employs database locking, as opposed to row or column locking like mysql or postgresql. If you want to do two things at the same time try using mysql, or postgresql. In mysql you would have to create the database. Your code would then look something like this:
$servername = "localhost";
$username = "username";
$password = "password";
try {
$conn = new PDO("mysql:host=$servername;dbname=myDB", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected successfully";
}
catch(PDOException $e)
{
echo "Connection failed: " . $e->getMessage();
}
$count = $conn->exec("INSERT into 'foo' ('data') values ('bar')");
$conn = null // close connection
I have written that seems to not be working, but MySQL does not return any error. It is supposed to get data from database1.table to update database2.table.column
<?php
$dbh1 = mysql_connect('localhost', 'tendesig_zink', 'password') or die("Unable to connect to MySQL");
$dbh2 = mysql_connect('localhost', 'tendesig_zink', 'password', true) or die("Unable to connect to MySQL");
mysql_select_db('tendesig_zink_dev', $dbh1);
mysql_select_db('tendesig_zink_production', $dbh2);
$query = " UPDATE
tendesig_zink_dev.euid0_hikashop_product,
tendeig_zink_production.euid0_hikashop_product
SET
tendesig_zink_dev.euid0_hikashop_product.product_quantity = tendesig_zink_production.euid0_hikashop_product.product_quantity
WHERE
tendesig_zink_dev.euid0_hikashop_product.product_id = tendesig_zink_production.euid0_hikashop_product.product_id";
if (mysql_query($query, $dbh1 ))
{
echo "Record inserted";
}
else
{
echo "Error inserting record: " . mysql_error();
}
?>
The manual page for mysql_error() mentions this about the optional parameter you're omitting:
link_identifier
The MySQL connection. If the link identifier is not
specified, the last link opened by mysql_connect() is assumed. If no
such link is found, it will try to create one as if mysql_connect()
was called with no arguments. If no connection is found or
established, an E_WARNING level error is generated.
So it's reading errors from $dbh2, which is the last connection you've opened. However, you never run any query on $dbh2:
mysql_query($query, $dbh1 )
Thus you get no errors because you are reading errors from the wrong connection.
The solution is to be explicit:
mysql_error($dbh1)
As about what you're trying to accomplish, while you can open as many connections as you want, those connections won't merge as you seem to expect: they're independent sessions to all effects.
All your tables are on the same server and you connect with the same users, there's absolutely no need to even use two connections anyway.
You can't just issue a cross-database update statement from PHP like that!
You will need to execute a query to read data from the source db (execute that on the source database connection: $dbh2 in your example) and then separately write and execute a query to insert/update the target database (execute the insert/update query on the target database connection: $dbh1 in your example).
Essentially, you'll end up with a loop that reads data from the source, and executes the update query on each iteration, for each value you're reading from the source.
I appreciate everyone's help/banter, here is what finally worked for me.
<?php
$dba = mysqli_connect('localhost', 'tendesig_zink', 'pswd', 'tendesig_zink_production') or die("Unable to connect to MySQL");
$query = " UPDATE
tendesig_zink_dev.euid0_hikashop_product, tendesig_zink_production.euid0_hikashop_product
SET
tendesig_zink_dev.euid0_hikashop_product.product_quantity = tendesig_zink_production.euid0_hikashop_product.product_quantity
WHERE
tendesig_zink_dev.euid0_hikashop_product.product_id = tendesig_zink_production.euid0_hikashop_product.product_id";
if (mysqli_query($dba, $query))
{
echo "Records inserted";
}
else
{
echo "Error inserting records: " . mysqli_error($dba);
}
?>
I have tried just about everything i can think of (and searched plenty of threads here on Stack)
I am using the following:
try {
$db = new PDO('mysql:host=localhost;dbname=data', 'user', 'pass');
}catch (PDOException $e){
exit('Database Error.');
}
$fileName="file.txt";
$query = <<<eof
LOAD DATA LOCAL INFILE '$fileName' INTO TABLE data FIELDS TERMINATED BY '|' LINES TERMINATED BY '\r\n' (email, ip, referalurl, date, firstname, lastname);
eof;
$db->query($query);
echo "success";
now in my file (yes im aware its a .txt) its formated like below:
email#gmail.com|IP.IP.IP.IP|yourdomain.com|"2013-12-22 12:03:29"|firstname|lastname
any suggestions would be great.. btw the database connection is successful but no data ever gets saved into mysql for some reason..
I decided to go with mysqlimport (bash)
I want to wean myself from the teat of the old mysql extension and am just doing a test PDO connection and simple query on a table in a database. I seem to be able to connect, ('connection successful' echoes out) but that's where the good times end. I have spent way too much time now just trying to get started with PDO.
<?php
$host = 'localhost';
$port = '3306';
$username = 'user';
$password = 'blabla';
$database = 'workslist';
try {
$db = new PDO("mysql:host=$host; port = $port; dbname = $database", $username, $password);
echo 'connection successful<br />';
$query = 'SELECT * FROM main';
$statement = $db->prepare($query);
$statement->execute();
$results = $statement->fetchAll();
$statement->closeCursor();
foreach($results as $r){
echo $r['work'] . '<br />';
}
} catch (PDOException $e) {
echo 'Error!: ' . $e->getMessage() . '<br />';
die();
}
?>
Is there anything wrong with the above?
The database name is 'workslist', the table name is 'main', and 'work' is one of the columns in that table. The PHP version I'm using is 5.3.4, and am using wamp on win7. I ran phpinfo() and under the PDO heading, the PDO drivers mysql, sqlite are enabled. To be sure the database and table actually exist I've tried it with MySQL and can return rows with the old mysql_fetch_array() method. I've checked the php.ini file to make sure the "extension=php_pdo..." lines are all uncommented.
cheers
This should work.
Please double-check that you actually have a table named "main" in that database.
Note that this error will not be discovered by PDO until you execute() the query, and if there is a problem with your query the default behavior is to return an empty result, not throw an exception.
To make PDO noisier, add the PDO::ERRMODE_EXCEPTION option when constructing PDO:
$db = new PDO("mysql:host=$host;port=$port;dbname=$database", $username, $password,
array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION)
);
Now check if you see the following:
Error!: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'workslist.main' doesn't exist
The particular problem is that spaces aren't allowed in the DSN string. With the spaces, the "dbname" directive isn't processed, so there's no default database. Besides removing the spaces, explicitly specifying the database in the statement can help prevent this sort of problem:
SELECT `work` FROM `workslist`.`main`
That way, should there not be a default database for some reason, the query will still succeed.
PDO won't throw an error unless you configure it to:
$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );