When making a new connection with PDO:
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
It appears you have to specify a database in the DB_DSN, e.g.
mysql:dbname=mydatabase
I have however just discovered that this does not limit subsequent queries using this connection to just this database. Any other databases that DB_USERNAME has permissions for can be used. All it appears to do is specify a default.
It has revealed for me that sometimes, queries were not being specific enough and thus a risk that a table in the wrong database would be accessed.
I am thinking I should create a dummy database, make all connections to that database, thus forcing all queries to include the database name explicitly.
Or: is there a way to make a connection exclusive to a given database?
What is best practice here?
Options on that:
use db name in querys SELECT * FROM dbname.tblname
create an sql mapper class that selects the database before each query new SQLMapper($databasename,$connection); & mysql_select_db($this->dbname,$this->con) in query() method
use DOCTRINE or something like that, they handle that for you
give an dbuser only access to one database (forces devs to use the right instance & no db change)
Use what is usefull in given cases, there is no best solution.
Its mostly about how much control over the code in your application you have.
If rules are followed, then everything should be fine.
Related
I have four databases with different tables, let's call the databases admindata, userdata, pagedata and mediadata.
At the moment I use one instance of mysqli for all databases:
$mysqli = new mysqli(...);
I keep this instance open until the end of the page load. I was not sure about the performance so I made databases switches like this when I had multiple queries in one script:
$mysqli->query('SELECT fields FROM database1.table1');
$mysqli->query('SELECT fields FROM database2.table2');
instead of:
$mysqli->select_db('database1');
$mysqli->query('SELECT fields FROM table1');
$mysqli->select_db('database2');
$mysqli->query('SELECT fields FROM table2');
What of those two is better in performance? Or is it even better to hold one instance of mysqli for every database like this:
$mysqli->query('SELECT fields FROM table1');
$mysqli2 = new mysqli(...);
$mysqli2->query('SELECT fields FROM table2');
EDIT:
On php.net someone wrote two years ago:
In some situations its useful to use this function for changing databases in general. We've tested it in production environment and it seams to be faster with switching databases than creating new connections.
http://ch2.php.net/mysqli_select_db
It would be nice to hear more about it.
I was teached that is better to hold separate connection per database / per user. Not just because of matter of security, but also a flexibility of your code. In the future, if you would like to start using ORM, it will be very difficuilt to rewrite the code that uses single connection for several databases. It may also help with debugging the database problems.
On other hand there's potential problem of having many connections per request. In the project im leading, we do use separate connections, but we pay attention on closing them when they are not needed anymore.
I think there's no universal solution, and all depends from your own needs and requirements.
I know this sounds very stupid indeed, but I find mysqli prepared statements and its object-oriented approach attractive so I plan on converting some of my past doodles from mysql to mysqli.
Here it is... The question
In mysql I used to have a configuration file, for example included in every file that needs the database (i.e. require('sys/dbconfig.php');)
I am not sure if I need to do this in mysqli, or do so as others say, open a connection when you need it, close it when you don't need it (i.e. stick $mysqli = new mysqli($host, $user, $pass, $database); everywhere it needs database transactions.
I do it like that:
config.php
define("DB_HOST", "127.0.0.1");
define("DB_NAME", "demo");
define("DB_USER", "root");
define("DB_PASS", "root");
database.php
// include database constants
include_once("config.php");
// create db connection
$db = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
now you can make SQL statements via
$result = $db->query("SELECT x FROM y;");
MySqlI comes in 2 flavours: procedural and object oriented.
When you use the procedural style everything stays the same as in mysqli_.
You are refering to the object oriented style and there the configuration is different .. more object oriented actually. That means that you have to create a new instance of mysqli and use its methods to get the job done.
Note: when using mysqli_ the same way as mysql you will have the same problems with SQL injection. You should use mysqli in combination with prepared queries and parameter binding.
Mysqli opens the connection when it is instantiated with new mysqli(...) (so does PDO).
During a PHP session you should not need to open/close connections to the database because the duration of a PHP session (for normal websites/webapps) is less than 1 second.
Forcing the equivalent of mysql_connect/mysql_close multiple times in the code can be helpful only in long running scripts that do not need an active connection for their entire duration.
The number of separate mysql connections allowed per mysql user is limited depending on the configuration of you server.
If you have some script that runs a long time and that will likely intersect many other scripts, you may use-up all of the allowed connections per user and thus block other users.
I would suggest (as a simple approach) to instantiate mysqli in a file that you will include everywhere you need db access use the variable you stored the mysqli object everywhere you need it using global $db.
I tend to create constants in a config file like Panique does.
I also create an App class with a static method fetch_db that contains the code for the connection. Then whenever I need a db connection I just call App::fetch_db().
I can post the code and a little more explanation later this afternoon when I get home.
I just started using mysqli API for PHP. Apparently, every time an object of the class MYSQLI is instantiated, it can setup a connection to the database as it connects to the server unlike mysql_connect, which connects to the server first and then you are required to specify the database to query.
Now this is a good problem if the db exists, in my case, the db does not exist on the first ever connection to the server/execution of the problem, hence I must connect without specifying the database, which is fine, since the msyqli constructor does not make this database mandatory.
My challenge is essentially, how do I check if the database exists before attempting the first connection. The only way to really do this would be to establish a conection to the server and then use the result of the following query to gauge if the database exists:
SELECT COUNT(*) AS `exists` FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMATA.SCHEMA_NAME="dbname" ;
If this returns true, then the database exists, but now the challenge is how do I get the mysqli object to query this database rather than having to prefix the name of the database in the query.
Thanks much
USE databasename as a query alters the current working database. or you can of course use $mysqli->select_db('databasename');
I am using multiple databases using CodeIgniter Active Records class. I had to disable persistent connection with MySQL, because CodeIgniter Active Records class can't make persistent connections using multiple databases.
I am looking at the load of my database, it seems like it's using most of it's queries calling "change database" and I am not sure if that's a good sign.
How can I optimize this without having to call "change database" all the time?
It's not as user friendly as most of the Active Record commands, but you can call the SQL directly like this:
$query = $this->db->query("SELECT * FROM database_a.some_table");
$query2 = $this->db->query("SELECT * FROM database_b.another_table");
Are you using queries that reference both databases? If not, it's not too difficult to load a new DB instance for the second database. I.e. you'd still use $this->db for the first, but you could have $this->db2 for the second. I honestly have no idea if that would trigger the "change database" command you're talking about, but it would be MUCH more sustainable code, at least. CI could keep its connections to each database open for the duration of the script (not a persistent connection), and it seems your problem would be fixed.
I've never needed multiple mysql databases in a single app, so this is entirely a guess based on what I've seen with, say, one mysql db and another being an sqlite db.
In my PHP program I need to hit the database between 0 and 3 times on any given webpage request. I am using PDO to interact with MySQL. First I create a database connection using something like this:
$dbh = new PDO("mysql:host=$hostname;dbname=animals", $username, $password);
Then I do what I need to do and close the connection like this:
$dbh = null;
I open and close a connection 0-3 times right now, the same number of times I need to interact with MySQL.
My question is, should I be re-using this connection instead? My queries are not one after another, they are scattered throughout my program and I don't really think it would be easy to run them one right after another.
So is it better to create a new database connection and close it for each interaction (query) or to just leave the connection open and reuse it? Does it make any difference?
Thanks!
For a typical website page, you should be reusing the same connection for all queries.
It's not worth it to spend time disconnecting and reconnecting.
Unless your pages take a huge amount of time to run (huge being relative), then there's no point in relinquishing a connection. You'll end up wasting more cycles on connectiong/disconnecting than you do actually executing queries. MySQL's pretty lightweight as far as connections go, but it still adds up.
The site says: "You must have 50 reputations to comment". My reputation is pretty bad so I can't leave a comment, but I want to add a notice on:
For a typical website page, you should be reusing the same connection
for all queries.
Absolutely right, but in case of need atypical script (e.g. compare tables between a remote database and local database) one can't use the same connection. Must close first connection and establish new one or have 2 separate connections (using different names) at the same time.
I prefer the second option in this case because of closing connection using "$dbh = null;" it can be a bit difficult in some cases. (PDO closing connection)
Here is explanation [from documentation: https://www.php.net/manual/en/pdo.connections.php ] why should be careful with "$dbh = null;" (it should be closed all instances too):
<?php
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
// use the connection here
$sth = $dbh->query('SELECT * FROM foo');
// and now we're done; close it
$sth = null;
$dbh = null;
?>
So, only $dbh = null; (without nullifying instances) is not a good idea.