Create MySQL user and database from PHP - php

Is there a way to create a new MySQL database, a new MySQL user and give the new user privileges on the new database all using PHP?
EDIT - should be pointed out this is run from 1 server to another, so Server A trying to install a DB/user on Server B
i've got this:
$con = mysql_connect("REMOTE.IP.ADDRESS","root","pass");
mysql_query("CREATE DATABASE ".$db."",$con)or die(mysql_error());
mysql_query("GRANT ALL ON ".$db.".* to ".$user." identified by '".$dbpass."'",$con) or die(mysql_error());
but i'm getting an error on the grant query:
"Access denied for user 'root'#'MY.REMOTE.SERVER.HOST.NAME' to database 'dbname'"

This answer has been edited several times based on new info provided by the OP
Is root actually allowed to connect to the server from the host that you are connecting from? If the error string is returning the canonical name of the server, there's a very good chance that 'localhost' is not pointing to 127.0.0.1 :
"Access denied for user
'root'#'MY.SERVER.HOST.NAME' to
database 'dbname'"
That should echo something like "Access denied for user 'root'#localhost'", not the name of the server.
Try:
$con = mysql_connect("127.0.0.1","root","pass");
Edit (After more information provided in comments)
If you are connecting from a totally different host, you have to tell MySQL user#remote_hostname_or_ip is allowed to connect, and has appropriate privileges to create a database and users.
You can do this rather easily using phpmyadmin (on the MySQL server), or a query like:
CREATE USER 'root'#'192.168.1.1' IDENTIFIED BY PASSWORD 'secret';
GRANT ALL PRIVILEGES ON * . * TO 'root'#'192.168.1.1' IDENTIFIED BY PASSWORD 'secret' WITH GRANT OPTION MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ;
I would advise not naming this user 'root' , just create a user with all of the global privileges needed. In the example, I used 192.168.1.1, that could easily be a hostname, just make sure DNS is set up appropriately. Specify the host to match exactly as it appears in logs when you connect to the remote server.
You may also want to adjust limits to taste. More information on the CREATE USER syntax can be found here, GRANT here.
Edit
If using MySQL 4 - CREATE is not an option. You would just use GRANT (4.1 Docs On User Management)
Edit
If using C-Panel, just use the API. While yes, it does have its quirks, its easier to maintain stuff that uses it rather than ad-hoc work arounds. A lot of successful applications use it without issue. Like any other API, you need to stay on top of changes when using it.

I believe you'd have to create a connection (with the root user) to an existing database (like mysql) and then run the create query.

You don't see a database connect in this example for the obvious reason: it is supposed that you learned already that any database action requires connect first.
It's the way the books being written: the things from the previous lessons being omitted in the next ones. Or every chapter will be 2 times bigger and you'll never finish the book.
so yes, you need to connect to the database first, using mysql_connect().
to create a user you can use mysql GRANT query
though I am never done it from the script but from the shell only

You would need to connect to the sql server first:
$conn=#mysql_connect(DB_HOST, DB_USER, DB_PASSWORD)
or die("Err:Conn");
Then the query will execute. A lot of shared hosting servers disable the creation of databases via PHP though.

Related

Not able to change privileges with MySQL database

I am looking to backup a MySQL database. When the following command is entered into the command line it works:
SELECT * INTO OUTFILE 'backup.txt' FROM table_name;
The file backup.txt is created. All is well.
When the above command is submitted via the MySQL query in a php file:
mysql_query("SELECT * INTO OUTFILE 'backup.txt' FROM table_name");
it does not work. The file backup.txt is not created.
Next, the privileges were looked at and the following command was entered using the command line:
GRANT FILE ON *.* TO 'root'#'localhost';
This command was accepted but the MySQL query still does not work.
The complete php file is shown below:
// connect to db host
//mysql_connect(DATABASE_HOST, DATABASE_USERNAME, DATABASE_PASSWORD)
$connection = mysql_connect("localhost", "mysql -u root", "")
or die('Could not connect: ' . mysql_error($connection));
// select db
$db = mysql_select_db("test", $connection);
// change privileges
mysql_query("GRANT FILE ON *.* TO 'root'#'localhost'");
// create query
$query = "SELECT * INTO OUTFILE 'backup.txt' FROM table_name";
//perform query
mysql_query($query);
// close mysql connection
mysql_close($connection);
Can anybody explain what is happening here and how I can get the MySQL query to work and create the outfile backup.txt.
WampServer on a Windows machine is being used.
At the moment I run mysql command line (MCL), I am an o/s user that has rights (let's call them creds for credentials) at some level to all o/s directories. Let's say the creds don't change for the duration of this code attempt, can't imagine they would. Point is, I am that user with those creds.
Without a path, full or relative just as you did, MCL writes to the data directory for the schema in the outfile call. So for instance on my system at the moment that would be
C:\Users\All Users\MySQL\MySQL Server 5.6\data\so_gibberish
where so_gibberish is the schema/db name that I would have gotten into with the use so_gibberish command or supplied as the db to use upon running mysql command line with a switch. Or it would be some linux path equivalent.
Via the MCL, I would have gotten into a db (use), as opposed to an MCL connect with no use. Meaning that I would not have issued the outfile command prior to getting into a db sandboxed, most likely (I am making the point later as it relates to Error 1046). And your command would have dumped the .txt file there (the above path a ways up) on my system. And it did in my test.
Now on to PHP.
If you are running a PHP script that connects but does not use the mysql_select_db function, then
Error 1046: No database selected
would have returned only if you were running code like the below to check for an error:
<?php
//error_reporting(E_ALL);
//ini_set('display_errors', 1);
...
... (load credential variables used below)
...
$link = mysql_connect($dbhost, $dbuser, $dbpass) or die("Unable to Connect to '$dbhost'");
//mysql_select_db($dbname) or die("Could not open the db '$dbname'");
echo "I made it here<br/>";
$test_query = "SELECT * INTO OUTFILE 'file456.txt' FROM mytable";
$result = mysql_query($test_query);
echo mysql_errno($link) . ": " . mysql_error($link) . "<br>";
mysql_close($link);
Not that people tend to check for errors. I would wager you are not in this call. They just plow foward thinking all is well.
Note though that error_reporting has no impact on this. What does impact it is whether or not you are checking for errors after mysql_query. You can rem out or clear rems and test this theory as I did. So you could be getting the 1046 Error and not know it.
Now there is the case for what o/s users and therefore the creds that the php to mysql process is masquerading as. This is driven by the original setup. Now why is this important? Because that user/those creds can very well be different than those used when at the o/s prompt you did the very first part of this using the MCL.
It is possible that the file is created thru php, but as you are not pathing with a full path to the file, just the filename, it might be sitting somewhere on your system without you knowing it, if you were to check for errors and none arrive. To test this theory, include the above error check after mysql_user without a full path, and do a directory scan to find it.
So in my test, in MCL I write out file123.txt, and in php I write out file456.txt (or whatever). And barring any error messages, I scan the file system to see where they showed up.
You would not be the first person to think OUTFILE failed, only later, maybe months later, find residue files in some directory and have a eureka moment: Oh yeah, I remember those files, what are they doing here?
It is possible that the call simply fails because of a creds issue from PHP, having to do with user or group world or some other setup chmod issue.
Via PHP, fully pathing to the outfile such as /full/path/here/out123.txt can have a good solution if the o/s user masquerading has the creds. But, in hosted environments, you can't simply say make it /tmp/out123.txt, as you will fail with permissions there. So there is no broad brush stroke "plug in this answer" that is going to solve it without a somewhat decent tinkering session by you.
So in summary for PHP, I would look into the following:
The file is being written out, you just don't know where.
The file fails but you don't know it because of no error checking after
mysql_query (such as a general mysql error, no db selected,
whatever).
Creds issue due to the o/s user masquerading from PHP into
mysql and is creds at the o/s file system level required for that
file i/o.
As for the Error 1221 error, as mentioned in comments and link to that part of it, you cannot GRANT FILE on a single db. That answer type was provided here

How can I solve permissions error when importing MySQL databases with PHPMyAdmin?

I'm developing a web site that is based around a MySQL db.
Because I wanted to do it off-line first, I installed WAMP server on my machine. This has Apache, an SQL server, and PHP.
I created a database on my off-line machine. The database is calledOffDB, created by user OffUser, with password OffPwd. I have exported it to an SQL file (less than one MB).
I want to import this db into my online db, which is called OnDB, created by user OnUser, with password OnUser. When I try to import in PHPMyAdmin, I get the following error:
"User OnUser doesn't have permissions to access databse OffDB"
In the off-line PHPMyAdmin, I added a new user, OnUser, with password OnPwd, and granted it all permissions to OffDB. Then I exported OffDB again, and atempted to import again. It failed with the same error. Same thing if I add new off-line user OnUser, with password OffPwd, and grant it permission - upon import I always get the error.
How can I solve that?
You need to add the OffUser and OffDB to the live server, not the other way around.
Alternatively, make a backup that does not specify the database name and users (for the latter, look for options involving GRANTs, and disable those). mysqldump should have options for that, at least if you use the mysqldump <database_name> variant, as should PHPMyAdmin.

"max_questions" limit not respected when running MySQL query via PHP

I'm using MySQL Community Server 5.5 with PHP 5.3.3 on a Windows Server 2008 platform.
I have set up per user resources limits, particularly a limit related to the queries run by a DB user within one hour. I have read this document and it is very interesting but always it doesn't work for me.
http://dev.mysql.com/doc/refman/5.5/en/user-resources.html
When I run a query via mysql command line tool (mysql.exe) the limit works properly and if the queries limit per hour was 7, after 7 queries within one hour I receive the error:
ERROR 1226 (42000): User 'user' has
exceeded the 'max_questions' resource
(current value: 7)
This above is the wanted behavior.
When I run a query via PHP (The user I have used to connect to the DB is the same above), the queries limit doesn't work: the same user via php can run all the queries it wants and without any limit. And if I come back on the mysql command line above the counter seems to be reset (even if the hour hasn't elapsed) : I can run 7 queries within an hour too.
I think this isn't the wanted behaviour. It seems that PHP resets the counter and doesn't trigger the queries limit.
PS: The 'user' owns only SELECT,INSERT,UPDATE,DELETE privileges and in the PHP code there isn't any SQL code as FLUSH USER_RESOURCES that the user 'user' couldn't have run (because RELOAD privilege isn't assigned to the user)
Thanks in advance
Check this tip,
how many users do you have in your mysql with the same name..(remember not only the name but the host where is permited to connect the user is specified in mysql ). **VERY IMPORTANT.
user#%
user#127.0.0.1
user#localhost
user#172.35.20.12
each one of them are not the same, if you have any limit rule do you like to use, so, you must assign limitations to the user#wherever you want the limintation. (all of them, if you have problems **think is your case).
Recomendation: create a specific user for WEB PHP (only one user#host must be created) , instead using a generic user with may have several users#hosts assigned.
like phpuser#'localhost' typically is enough.
I think you are doing little mistake,
Please check for the host in your mysql_connect function into php.
if your host is IP address then you need to assign the resource limit to username#yourip or username#%
If you are running through the command line then you are login from username#localhost and you have assign the limit to the same user.
Please try my above tricks and let me know if you are having problem still ?
Happy coding....
I have solved (partially) the problem.
The problem occurs only when the query including the MAX_QUERIES_PER_HOUR component includes also one of the following elements different from 0:
MAX_CONNECTIONS_PER_HOUR !=0
MAX_USER_CONNECTIONS !=0;
e.g. the following grant query won't ever cause the error message related to the queries limit achievement in PHP:
GRANT USAGE ON *.* TO 'user'#'localhost'
WITH MAX_QUERIES_PER_HOUR 20
MAX_UPDATES_PER_HOUR 10
MAX_CONNECTIONS_PER_HOUR 5
MAX_USER_CONNECTIONS 2;
Instead the following grant works correctly and MySQL applies the limits correctly.
GRANT USAGE ON *.* TO 'user'#'localhost'
WITH MAX_QUERIES_PER_HOUR 20
MAX_UPDATES_PER_HOUR 10
MAX_CONNECTIONS_PER_HOUR 0
MAX_USER_CONNECTIONS 0;
In short, when the query setting queries limit includes one of the components, MAX_CONNECTIONS_PER_HOUR and MAX_USER_CONNECTIONS different from 0, the limits related to the MAX_QUERIES_PER_HOUR and MAX_UPDATES_PER_HOUR are ignored: my PHP pages can perform all the queries they want. Otherwise the limit is understood and the message
has exceeded the 'max_questions' resource
correctly is showed when the queries limit achievement event occurs.
As I said above the problem doesn't occurs when I use the mysql command line tool. It occurs only when queries are run through PHP pages.

connecting to another db from one server

Ok so I have a client that is trying to move half his site to another server...in this i still need to pull data from both databases. SO i have the new site and i need to do a mysql db query on the old site so i can include the old nav....but when i do
<?php include("http://www.othersite.com/includes/db.php"); ?>
<?php include("http://www.othersite.com/includes/nav.php"); ?>
I get
Warning: mysql_query(): Access denied for user 'www-data'#'localhost'
(using password: NO) in /vol/www/othersite.com/public_html/includes/nav.php
on line 223 Warning:
How do i access another db from the new site and not allow it to interfere with the new db connection
you can use:
$newLink = mysql_connect($host, $user, $password);
mysql_select_db($db, $newLink);
and the you should add the $newLink to your queries so it will not use the "old" database link connection, like:
mysql_query('SELECT * FROM USERS', $newLink);
Hope it helps
P.S. It'll be more easy if you put the code from db.php and nav.php
You'd need to show us the actual code used to connect to these dataases (with passwords blanked out). But even without it I can tell you that the remote server is NOT called localhost.
It seems you're including these files from the remote site. It won't work this way, since the code is still executed on local server.
You must also make sure, that the remote MySQL allows remote connections, and that there is a MySQL user account with appropriate privileges created.
See: http://dev.mysql.com/doc/refman/5.5/en/privilege-system.html
...in this i still need to pull data
from both databases.
Good luck with this!
The way I would do this:
Copy code to server #2
Adjust it to fetch data from server #1
Change DNS record from ip of server #1 to ip of server #2
Wait 1 day
Give blocking 'server maintenance' for 5 minutes on server #1
rsync db from server #2 to #1 / adjust server #2 to fetch data from itself
Remove 'server maintenance'
Sell server #1 on ebay and get boozed
NOTE:
Sure, if you are talking about some private host.. There are far more successful yet complicated mechanisms to do the same without putting server offline.
Load http://www.othersite.com/includes/db.php in your browser. You'll notice that you cannot see the PHP code: what you obtain is the output of the PHP code. That means than changing all your ìnclude constructs to point to a remote HTTP server will simply break your site since you'll no longer have access to the source code.
Now, answering to your question, if you want to connect to a remote database you must find wherever you have the DB password and change the data: localhost with the new server address, www-data with your new user, etc. However, you probably need to configure the remote MySQL server so it accepts external connections from your new server's IP address.

MySQL Error "Too many connections"

I am using MySQL 5.0 for a site that is hosted by GoDaddy (linux).
I was doing some testing on my web app, and suddenly I noticed that the pages were refreshing really slowly. Finally, after a long wait, I got to a page that said something along the lines of "MySQL Error, Too many connections...", and it pointed to my config.php file which connects to the database.
It has just been me connecting to the database, no other users. On each of my pages, I include the config.php file at the top, and close the mysql connection at the end of the page. There may be several queries in between. I fear that I am not closing mysql connections enough (mysql_close()).
However, when I try to close them after running a query, I receive connection errors on the page. My pages are PHP and HTML. When I try to close a query, it seems that the next one won't connect. Would I have to include config.php again after the close in order to connect?
This error scared me because in 2 weeks, about 84 people start using this web application.
Thanks.
EDIT:
Here is some pseudo-code of my page:
require_once('../scripts/config.php');
<?php
mysql_query..
if(this button is pressed){
mysql_query...
}
if(this button is pressed){
mysql_query...
}
if(this button is pressed){
mysql_query...
}
?>
some html..
..
..
..
..
<?php
another mysql_query...
?>
some more html..
..
..
<?php mysql_close(); ?>
I figured that this way, each time the page opens, the connection opens, and then the connection closes when the page is done loading. Then, the connection opens again when someone clicks a button on the page, and so on...
EDIT:
Okay, so I just got off the phone with GoDaddy. Apparently, with my Economy Package, I'm limited to 50 connections at a time. While my issue today happened with only me accessing the site, they said that they were having some server problems earlier. However, seeing as how I am going to have 84 users for my web app, I should probably upgrade to "Deluxe", which allows for 100 connections at a time. On a given day, there may be around 30 users accessing my site at a time, so I think the 100 would be a safer bet. Do you guys agree?
Shared-hosting providers generally allow a pretty small amount of simultaneous connections for the same user.
What your code does is :
open a connection to the MySQL server
do it's stuff (generating the page)
close the connection at the end of the page.
The last step, when done at the end of the page is not mandatory : (quoting mysql_close's manual) :
Using mysql_close() isn't usually
necessary, as non-persistent open
links are automatically closed at the
end of the script's execution.
But note you probably shouldn't use persistent connections anyway...
Two tips :
use mysql_connect insead of mysql_pconnect (already OK for you)
Set the fourth parameter of mysql_connect to false (already OK for you, as it's the default value) : (quoting the manual) :
If a second call is made to
mysql_connect() with the same
arguments, no new link will be
established, but instead, the link
identifier of the already opened link
will be returned.
The new_link
parameter modifies this behavior and
makes mysql_connect() always open a
new link, even if mysql_connect() was
called before with the same
parameters.
What could cause the problem, then ?
Maybe you are trying to access several pages in parallel (using multiple tabs in your browser, for instance), which will simulate several users using the website at the same time ?
If you have many users using the site at the same time and the code between mysql_connect and the closing of the connection takes lots of time, it will mean many connections being opened at the same time... And you'll reach the limit :-(
Still, as you are the only user of the application, considering you have up to 200 simultaneous connections allowed, there is something odd going on...
Well, thinking about "too many connections" and "max_connections"...
If I remember correctly, max_connections does not limit the number of connections you can open to the MySQL Server, but the total number of connections that can bo opened to that server, by anyone connecting to it.
Quoting MySQL's documentation on Too many connections :
If you get a Too many connections
error when you try to connect to the
mysqld server, this means that all
available connections are in use by
other clients.
The number of connections allowed is
controlled by the max_connections
system variable. Its default value is
100. If you need to support more connections, you should set a larger
value for this variable.
So, actually, the problem might not come from you nor your code (which looks fine, actually) : it might "just" be that you are not the only one trying to connect to that MySQL server (remember, "shared hosting"), and that there are too many people using it at the same time...
... And if I'm right and it's that, there's nothing you can do to solve the problem : as long as there are too many databases / users on that server and that max_connection is set to 200, you will continue suffering...
As a sidenote : before going back to GoDaddy asking them about that, it would be nice if someone could validate what I just said ^^
I had about 18 months of dealing with this (http://ianchanning.wordpress.com/2010/08/25/18-months-of-dealing-with-a-mysql-too-many-connections-error/)
The solutions I had (that would apply to you) in the end were:
tune the database according to MySQLTuner.
defragment the tables weekly based on this post
Defragmenting bash script from the post:
#!/bin/bash
# Get a list of all fragmented tables
FRAGMENTED_TABLES="$( mysql -e `use information_schema; SELECT TABLE_SCHEMA,TABLE_NAME
FROM TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema','mysql') AND
Data_free > 0` | grep -v '^+' | sed 's,t,.,' )"
for fragment in $FRAGMENTED_TABLES; do
database="$( echo $fragment | cut -d. -f1 )"
table="$( echo $fragment | cut -d. -f2 )"
[ $fragment != "TABLE_SCHEMA.TABLE_NAME" ] && mysql -e "USE $database;
OPTIMIZE TABLE $table;" > /dev/null 2>&1
done
Make sure you are not using persistent connections. This is usually a bad idea..
If you've got that .. At the very most you will need to support just as much connections as you have apache processes. Are you able to change the max_connections setting?
Are you completely sure that the database server is completely dedicated to you?
Log on to the datbase as root and use "SHOW PROCESSLIST" to see who's connected. Ideally hook this into your monitoring system to view how many connections there are over time and alert if there are too many.
The maximum database connections can be configured in my.cnf, but watch out for running out of memory or address space.
If you have shell access, use netstat to see how many sockets are opened to your database and where they come from.
On Linux, type:
netstat -n -a |grep 3306
On windows, type:
netstat -n -a |findstr 3306
The solution could one of these, i came across this in a MCQA test, even i did not understood which one is right!
Set this in my.cnf "set-variable=max_connections=200"
Execute the command "SET GLOBALmax_connections = 200"
Use always mysql_connect() function in order to connect to the mysql server
Use always mysql_pconnect() function in order to connect to the mysql server
Followings are possible solutions:
1) Increase the max connection setting by setting the global variable in mysql.
set global max_connection=200;
Note: It will increase the server load.
2) Empty your connection pool as below :
FLUSH HOSTS;
3) check your processList and kill specific processlist if you don't want any of them.
You may refer this :-
article link

Categories