I have an application where each user gets their own database where each database has the same schema.
I have a script that performs migrations in this fashion:
SHOW databases
Iterate through databases
Execute sql statements
This can take a long time when there are complicated queries that take a lot of time (3 or more seconds)
Is there a way where I can run the sql statements for each database at the same time from one script? Is this dangerous/too resource intensive to do this?
The reason I want to do this, is to prevent downtime as much as possible.
Here is my script now:
<?php
ini_set('display_errors', 1);
set_time_limit(0);
$sql = file_get_contents('../update.sql');
$sql_queries = explode(";", $sql);
$exclude_dbs = array('horde','phppoint_forums','phppoint_site','roundcube', 'pos', 'bntennis_site', 'mysql', 'information_schema', 'performance_schema');
$conn = mysqli_connect("localhost", "root", "PASSWORD");
$show_db_query = mysqli_query($conn, 'SHOW databases');
$databases = array();
while ($row = mysqli_fetch_assoc($show_db_query))
{
if (!in_array($row['Database'], $exclude_dbs))
{
$databases[] = $row['Database'];
}
}
foreach($databases as $database)
{
mysqli_select_db($conn, $database);
echo "Running queries on $database\n***********************************\n";
foreach($sql_queries as $query)
{
if (!empty($query))
{
echo "$query;";
if (!mysqli_query($conn, $query))
{
echo "\n\nERROR: ".mysqli_error($conn)."\n\n";
}
}
}
echo "\n\n";
}
?>
I don't know if the database will hold for that load but basically I would fork the process or spawn it into the background, depending on language.
For php you can fork the process for each database basically running the migrations in parallel.
Related
I'm trying to execute an Insert query to write data into a Database. I'm using Mysqli and PHP.
The code looks OK for me. However, every time I go to the webpage to check if the form works, the query gets executed an a new row is created in the DB (empty).
I'm pretty sure there is something wrong with the last if statement. Could you advise?
BTW, the snippet is only for the PHP to execute the sql query, since the form is working just fine.
Thanks!
$servername = "localhost";
$username = "root";
$password = "mysqlpassword";
$dbname = "bowieDB";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$album = $_POST['album'];
$relyear = $_POST['relyear'];
$label = $_POST['label'];
$chart = $_POST['chart'];
$track1 = $_POST['track1'];
$track2 = $_POST['track2'];
$track3 = $_POST['track3'];
$track4 = $_POST['track4'];
$track5 = $_POST['track5'];
$sql = "INSERT INTO Albums (album, relyear, label, chart, track1, track2, track3, track4, track5)
VALUES ('$album', '$relyear', '$label', '$chart', '$track1', '$track2', '$track3', '$track4', '$track5')";
$result = mysqli_query($conn, $sql);
if ($conn->query($sql) === TRUE) {
echo "New record created successfully";
} else {
echo "Error: " . $sql . "<br>" . $conn->error;
}
$conn->close();
You are mixing Procedural and Object Orientated SQL interactions.
This is Procedural:
$result = mysqli_query($conn, $sql);
This is Object Orientated:
$conn->query($sql)
You can not use both with the same connection details, you should do one or the other throughout your code. The best one to use is Object Orientated approach, so rework the Procedural code to:
$result = $conn->query($sql);
if ($result) {
...
So actually you can simply remove the line starting $result = ... and let the IF statement query you already have handle itself.
Other notes:
Use MySQL error feedback such as checking if(!empty($conn->error)){print $conn->error;} after SQL statements. See example code below...
Use the following PHP error feedback too, set at the very top of your PHP page:
...
error_reporting(E_ALL);
ini_set('display_errors',0);
ini_set('log_errors',1);
you need to read up and be aware of SQL injection that can destory your database should someone POST data that also happens to be MySQL commands such as DROP.
Code for Comment:
if ($_SERVER['REQUEST_METHOD'] == "POST") {
//run SQL query you already have coded and assume
// that the form has been filled in.
$result = $conn->query($sql);
if ($result) {
//all ok
}
if(!empty($conn->error)) {
print "SQL Error: ".$conn->error;
}
}
use
1. if(isset($_POST['Submit'])){//your code here }
and
2. if($result){...
if you are using procedural method
My cron job does not work and I was wandering if there is any PHP code which will stop it from forming.
I know how it works, but I want to know what kind go code will not read in PHP code.
One code I found out does not work is sessionstart() and $_SESSION because it saves it on the server like a cookie and cron job does not go through the server or something.
Therefore, is there any other code which will not work from your own knowledge like maybe file_get_contents or fopen() (I don't know if these don't work. Just giving ideas)
EDIT
<?php
$dbhost = "localhost";
$dbuser = "it32_2015";
$dbpass = "it32_2015";
$conn = mysql_connect($dbhost, $dbuser, $dbpass);
if(! $conn )
{
die('Could not connect: ' . mysql_error());
}
$sql = 'SELECT Title, Pubdate, Link FROM ytable';
mysql_select_db('it32_2015');
$retval = mysql_query( $sql, $conn );
if(! $retval )
{
die('Could not get data: ' . mysql_error());
}
while($row = mysql_fetch_array($retval, MYSQL_ASSOC))
{
$status .= "速報ニュース:".
"{$row['Title']} : ".
"ここでチェック!".
"{$row['Link']}".
"時間:".
"{$row['Pubdate']}".
" #yahoonews END";
}
$statusarray = explode(" END",$status);
$result = mysql_query('SELECT MIN(ID) AS min, MAX(ID) AS max FROM ytable') or exit(mysql_error());
$row = mysql_fetch_assoc($result);
$check = file_get_contents('/home/www2/it32.lady2.itall.co.jp/www/counter.php');
if($check < $row['max']){
if (is_numeric($check)){
$counter = ++$check;
}
}
$fp = fopen('/home/www2/it32.lady2.itall.co.jp/www/counter.php',"w+");
fwrite($fp, $counter);
fclose($fp);
require("/home/www2/it32.lady2.itall.co.jp/www/tweet.php");
?>
Is there any code I cannot use for cron in my code.
Cron jobs i.e. scheduled tasks are scripts that run periodically. As such, the script isn't meant to be interfaced with by a user. It is just meant to carry out an action. So the reason sessions don't work with cron jobs is because there is no user to start a session for. Any PHP function that requires a user to work (e.g. setcookie(), session_start()) will not work. All other functions will.
Edit:
All the functions in your script will work as intended.
I am Developing the simple application,the application related to database operations.
My doubt is how can i connect to multiple databases same time.
how can php knows which databases the data will store.
If the user enter the data which database it will enter,both databases or one database.
Please answer my question.i have struggling a lot for this question.
If you use PHP5 (And you should, given that PHP4 has been deprecated), you should use PDO, since this is slowly becoming the new standard. One (very) important benefit of PDO, is that it supports bound parameters, which makes for much more secure code.
You would connect through PDO, like this:
try {
$db = new PDO('mysql:dbname=databasename;host=127.0.0.1', 'username', 'password');
} catch (PDOException $ex) {
echo 'Connection failed: ' . $ex->getMessage();
}
(Of course replace databasename, username and password above)
You can then query the database like this:
$result = $db->query("select * from tablename");
foreach ($result as $row) {
echo $row['foo'] . "\n";
}
Or, if you have variables:
$stmt = $db->prepare("select * from tablename where id = :id");
$stmt->execute(array(':id' => 42));
$row = $stmt->fetch();
If you need multiple connections open at once, you can simply create multiple instances of PDO:
try {
$db1 = new PDO('mysql:dbname=databas1;host=127.0.0.1', 'username', 'password');
$db2 = new PDO('mysql:dbname=databas2;host=127.0.0.1', 'username', 'password');
} catch (PDOException $ex) {
echo 'Connection failed: ' . $ex->getMessage();
}
Yes you can.. by using two connection strings..
$mysqli1 = new mysqli('HOST1', 'USER1', 'PASSWORD1', 'DB_NAME1');
$mysqli2 = new mysqli('HOST2', 'USER2', 'PASSWORD2', 'DB_NAME2');
and your queries should be like
$result1 = $mysqli1->query('query ......');
and
$result2 = $mysqli2->query('query ......');
Of course you can given example below add more connections if you want:
Class database
{
private oracleDatabase;
private mysqlDatabase;
public function connOracle() {
$db = "";
$user = "";
$password = "";
try {
$this->oracleDatabase = new PDO("oci:dbname=".$db,$user,$password);
} catch(PDOException $e){
echo "Can't connect to database (Oracle). ". $e->getMessage();
}
}
public function connMysql() {
$db = "";
$user = "";
$password = "";
try {
$this->mysqlDatabase = new PDO("mysql:dbname=".$db,$user,$password);
} catch(PDOException $e){
echo "Can't connect to database (Mysql). ". $e->getMessage();
}
}
}
Be carefull if you are using two databases on the same server at the same time. By default mysql_connect returns the same connection ID for multiple calls with the same server parameters, which means if you do
<?php
$db1 = mysql_connect(...stuff...);
$db2 = mysql_connect(...stuff...);
mysql_select_db('db1', $db1);
mysql_select_db('db2', $db2);
?>
then $db1 will actually have selected the database 'db2', because the second call to mysql_connect just returned the already opened connection ID !
You have two options here, eiher you have to call mysql_select_db before each query you do, or if you're using php4.2+ there is a parameter to mysql_connect to force the creation of a new link.
Use this below link to refer.What you have asked here.
PHP Documentation
Yes, you may use multiple database in one application, but the main thing is when you are communicating with the dbname, you have to specify that dbname also so than script will communicate with only that db in which you had defined. Ex.
$db1 = mysql_connect(...stuff...);
$db2 = mysql_connect(...stuff...);
mysql_select_db('db1', $db1);
mysql_select_db('db2', $db2);
$resultsa = mysql_query('SELECT * FROM table_a', $dbname) or die('Could not query database_a');
Yes you can connect multiple databases.
open your php.ini file and give me your database details like
port number,username,password.
And after that you can give the queries like this in your applications
$db1 = mysql_connect($hostname, $username, $password);
$db2 = mysql_connect($hostname, $username, $password, true);
mysql_select_db('database1', $db1);
mysql_select_db('database2', $db2);
Then to query database 1, do this:
mysql_query('select * from tablename', $dbh1);
and for database 2:
mysql_query('select * from tablename', $dbh2);
i think this is work fine for your question.
Yes you can, in very basic terms, you do it like this:
http://au1.php.net/function.mysql-connect
$conn = mysql_open($host, $username, $password, true);
To connect to multiple databases on the same server:
$dblink1 = mysql_select_db('database_a', $conn);
$dblink2 = mysql_select_db('database_b', $conn);
To get results from two databases:
$resultsa = mysql_query('SELECT * FROM table_a', $dblink1) or die('Could not query database_a');
$resultsb = mysql_query('SELECT * FROM table_b', $dblink2) or die('Could not query database_b');
edit - keep in mind that the mysql_ functions aren't available in recent PHP releases because they've been removed.
Warning
This extension is deprecated as of PHP 5.5.0, and will be removed in
the future. Instead, the MySQLi or PDO_MySQL extension should be used.
See also MySQL: choosing an API guide and related FAQ for more
information.
The script below is used for updating schema of 100 databases.
I am making one call to mysql_connect, does mysql_select_db cause another connection to be made or am I ok? (I run this script to update the schema of 100 or so database)
$conn = mysql_connect("localhost", "root", "PASSWORD");
$show_db_query = mysql_query('SHOW databases');
$databases = array();
while ($row = mysql_fetch_assoc($show_db_query))
{
if (!in_array($row['Database'], $exclude_dbs))
{
$databases[] = $row['Database'];
}
}
foreach($databases as $database)
{
mysql_select_db($database, $conn);
echo "Running queries on $database\n***********************************\n";
foreach($sql_queries as $query)
{
if (!empty($query))
{
echo "$query;";
if (!mysql_query($query))
{
echo "\n\nERROR: ".mysql_error()."\n\n";
}
}
}
echo "\n\n";
}
As long as mysql_select_db found a last connection or a connection identifer is supplied with the calling statment, it does not create a new connection.
Since you are passing a connection identifer so it does not create a new connection to mysql. you are safe to go in this case of multiple connection but be aware that mysql extension is no longer maintained, you could try mysqli or PDO.
I've been told that authCode(); isn't being re-called in the most efficient way, as it will "stack a lot of DB connections, opening and closing them quickly which is expensive in respect to resources".
Here's my code:
function authCode() {
$num1 = mt_rand(1, 2147483647);
$num2 = mt_rand(1, 2147483647);
$authcode = dechex($num1).dechex($num2);;
include("../db/71cfde725dc86.php");
$conn = mysql_connect($db_host, $db_uname, $db_pword) or die("Couldn't connect because ".mysql_error()); mysql_select_db($db_name);
$query = "SELECT COUNT(*) FROM records WHERE valcode='$authcode'";
$result = mysql_query($query) or die("SELECT query failed due to ".mysql_error());
$count = mysql_fetch_assoc($result);
$row = $count['COUNT(*)'];
if($row > 0)
{
$authcode = authCode();
}
else
{
$query2 = "INSERT INTO records (valcode) VALUES ('$authcode')";
$result2 = mysql_query($query2) or die("INSERT query failed due to ".mysql_error());
}
mysql_close($conn);
return $authcode;
}
authCode();
I'm focusing on $authcode = authCode(); and the fact that the database connection isn't closed until the end, which means if it does re-call the connection is still open (so I have heard)?
Should I close the connection after $row is assigned, and then re-open and close within the else statement?
What you should be doing is opening the connection before the first call to authCode(), and passing it in as a parameter. That way you use a single connection for all calls.
There's absolutely no need to run this function recursively. It can be done far easier with less overhead using a simple while loop. In pseudo code:
function authCode() {
... connect to database ...
while (true) {
... generate random code ...
if (code is in database) {
continue;
} else {
insert code into data base
break;
}
}
return $code
}
No recursion, one single database handle.
And beyond this, why such a lousy code generator? You'll get a variable-length code, with high chance of collisions. Why not simply use sha1 with a properly salted source string, which is far far less likely to be collide than your version. Your code has a theoretical keyspace of 32 bits, while md5 is 128bit and sha2 is 160bit.
You could pass your database connection in the function :
function authCode($conn) {
if ($db_link == null) {
$has_instantiated_connection = true;
// set the connection
}
else
$has_instantiated_connection = false;
// stuff
// recall
authCode($conn)
if ($has_instantiated_connection)
// close the connection
}