Unused write database connections - php

This issue was raised using Laravel 5.0.
My project's database setup consists of 1 write node and multiple read-replicas (postgresql). Everytime a connection is initiated for any query, eg:
php
<?php $user = \App\User::find(1); ?>
... a connection is made to the write node. This occurs even when no writing queries are run (including set names 'utf8', etc); a connection will be set up, but all the SELECT queries are run correctly on the read-replicas.
How can I avoid this write connection if I don't need/use it for read-only requests?

There are two classes maintaining the DB connections: Illuminate/Database/DatabaseManager and Illuminate/Database/Connectors/ConnectionFactory.
When any Laravel class want to use a DB connection, it makes a call to DatabaseManager::connection(), which eventually request for an actual connection via ConnectionFactory::make().
Your issue lies here, the underlying of make() process creates both 'read' and 'write' connections at the same time. So 'write' connection is always established. It is a behavior of ConnectionFactory.
So the best way is opening an issue on Laravel asking the dev team whether they would like to improve the connection establishment only when it is actually needed.
Edited:
I just found that you already opened an issue :-)
https://github.com/laravel/framework/issues/10337

Related

Laravel: what happens if I have separate read/write connections configured, and do both reads and writes within a transaction?

If I have reads/writes configured in database.php, and I start a transaction like DB::transaction(function() { // series of reads and writes }), will everything run on the write connection, or will there be two separate transactions, or will it just explode?
https://github.com/laravel/framework/pull/3272
getReadPdo() now checks if the query is within a transaction, and in that case returns the same PDO connection as the write.
If you're saying you want to do both reads and writes within a transaction using the same connection, then that will work fine - you can read from the database during the transaction.
If you're saying you want to read using one connection while you're writing as part of a transaction on the other connection, that will work fine too although you might have times when the read connection will block until the write connection transaction is finished.

Connect to Multiple Databases in same/one connection

How could this be done within PHP. without reloading or adding an entire new connection.
MySQL has one connection, that gives you access to multiple databases.
Where you could call,
$this->db = my_database_connection;
$this->db->database_one->query();
$this->db->database_two->query();
and when those run, it understands which database it needs to utilize without creating a new db connection.
Is this even possible?
I have an application I want to run queries and data from multiple databases (with a heavy load of traffic) but I don't want to have it use 2 connections per user, seems inefficient. The databases have the same credentials for the connection (host,pass,user) but I have many database within that connection.

Where does codeigniter create and destroy mysql connection and is the db class singleton?

If we have multiple database groups in database.php:-
1) Do the connections of all of them are made even only one has to be used in a particular call. ie. if i have database groups a,b
And in my call i load model that is loading only group b.
2) If i have loaded two models in my controller and if both of them are loading same databases, would different connection will be made or same connection will be shared.
Ex:- controller mycont.php has following:-
$this->load->model('model1');
$this->load->model('model2');
If both model1.php and model2.php has following:-
$this->load->db('connection_name');
3) Where are the connections closed.
Ex:- If i have following code:-
$this->databaseFunc();//completes the database work nothing required after this
here a curl call is made which takes long time
So when does database connection is closed, after curl or it gets closed itself on over exceeding mysql_wait_time configuration at mysql server.
Hope the answer to this question will prove useful for understanding DB with codeigniter in a better way.
In CI, each library is a singleton. It is created on load->library and destroyed at the end of the request.
The database lib handle database connection, so the connection is closed when the library is destroyed. It has nothing to do with curl.
I've never tryed it but it should work like that.

CodeIgniter - only connect to database if there is a query to run

At the moment I load the database class in my autoload which automatically creates a connection to mysql. If there are no queries it will have still created a connection.
For performance I only want to connect to mysql if a query has been run.
What would be the best way to achieve this?
I am thinking of writing a model function that all queries run through which detects if the database has been connected to or not, and simply calls $this->load->database() if not before running $this->db->query().
The problem with this is that I would have to change all of my $this->db->query() references in my code which is a pain.
Ideally I would like to extend the $this->db->query() function to support this.
Any ideas?
You can modify the autoinit property of your database config
$db['mydb']['autoinit'] = false;
This will cause you database class to not initialize (which include connecting to the server) when instantiated, it will instead happen when the first query occurs.
See the database configuration page

PHP mySQL - When is the best time to disconnect from the database?

I use lazy connection to connect to my DB within my DB object. This basically means that it doesn't call mysql_connect() until the first query is handed to it, and it subsequently skips reconnecting from then on after.
Now I have a method in my DB class called disconnectFromDB() which pretty much calls mysql_close() and sets $_connected = FALSE (so the query() method will know to connect to the DB again). Should this be called after every query (as a private function) or externally via the object... because I was thinking something like (code is an example only)
$students = $db->query('SELECT id FROM students');
$teachers = $db->query('SELECT id FROM teachers');
Now if it was closing after every query, would this slow it down a lot as opposed to me just adding this line to the end
$db->disconnectFromDB();
Or should I just include that line above at the very end of the page?
What advantages/disadvantages do either have? What has worked best in your situation? Is there anything really wrong with forgetting to close the mySQL connection, besides a small loss of performance?
Appreciate taking your time to answer.
Thank you!
As far as I know, unless you are using persistent connections, your MySQL connection will be closed at the end of the page execution.
Therefore, you calling disconnect will add nothing and because you do the lazy connection, may cause a second connection to be created if you or another developer makes a mistake and disconnects at the wrong time.
Given that, I would just allow my connection to close automatically for me. Your pages should be executing quickly, therefore holding the connection for that small amount of time shouldn't cause any problems.
I just read this comment on PHP website regarding persistent connection and it might be interesting to know:
Here's a recap of important reasons
NOT to use persistent connections:
When you lock a table, normally it is unlocked when the connection
closes, but since persistent
connections do not close, any tables
you accidentally leave locked will
remain locked, and the only way to
unlock them is to wait for the
connection to timeout or kill the
process. The same locking problem
occurs with transactions. (See
comments below on 23-Apr-2002 &
12-Jul-2003)
Normally temporary tables are dropped when the connection closes,
but since persistent connections do
not close, temporary tables aren't so
temporary. If you do not explicitly
drop temporary tables when you are
done, that table will already exist
for a new client reusing the same
connection. The same problem occurs
with setting session variables. (See
comments below on 19-Nov-2004 &
07-Aug-2006)
If PHP and MySQL are on the same server or local network, the
connection time may be negligible, in
which case there is no advantage to
persistent connections.
Apache does not work well with persistent connections. When it
receives a request from a new client,
instead of using one of the available
children which already has a
persistent connection open, it tends
to spawn a new child, which must then
open a new database connection. This
causes excess processes which are just
sleeping, wasting resources, and
causing errors when you reach your
maximum connections, plus it defeats
any benefit of persistent connections.
(See comments below on 03-Feb-2004,
and the footnote at
http://devzone.zend.com/node/view/id/686#fn1)
(I was not the one that wrote the text above)
Don't bother disconnecting. The cost of checking $_connected before each query combined with the cost of actually calling $db->disconnectFromDB(); to do the closing will end up being more expensive than just letting PHP close the connection when it is finished with each page.
Reasoning:
1: If you leave the connection open till the end of the script:
PHP engine loops through internal array of mysql connections
PHP engine calls mysql_close() internally for each connection
2: If you close the connection yourself:
You have to check the value of $_connected for every single query. This means PHP has to check that the variable $_connected A) exists B) is a boolean and C) is true/false.
You have to call your 'disconnect' function, and function calls are one of the more expensive operations in PHP. PHP has to check that your function A) exists, B) is not private/protected and C) that you provided enough arguments to your function. It also has to create a copy of the $connection variable in the new local scope.
Then your 'disconnect' function will call mysql_close() which means PHP A) checks that mysql_close() exists and B) that you have provided all needed arguments to mysql_close() and C) that they are the correct type (mysql resource).
I might not be 100% correct here but I believe the odds are in my favour.
You may want to look at a using persistent connections. Here are two links to help you out
http://us2.php.net/manual/en/features.persistent-connections.php
http://us2.php.net/manual/en/function.mysql-pconnect.php
The basic unit of execution presumably is an entire script. What you first of all are wanting to apply resources (i.e. the database) to, efficiently and effectively, is the entirety of a single script.
However, PHP, Apache/IIS/whatever, have lives of their own; and they are capable of using the connections you open beyond the life of your script. That's the signficance of persistent (or pooled) connections.
Back to your script. It turns out you have a great deal of opportunity to be creative about using that connection during its execution.
The typical naive script will tend to hit the connection again and again, picking up locally appropriate scraps of data associated with given objects/modules/selected options. This is where procedural methodology can inflict a penalty on that connection by opening, requesting, receiving, and closing. (Note that any single query will remain alive until it is explicitly closed, or the script ends. Be careful to note that a connection and a query are not the same thing at all. Queries tie up tables; connections tie up ... connections (in most cases mapped to sockets). So you should be conscious of proper economy in the use of both.
The most economical strategy with regard to queries is to have as few as possible. I'll often try to construct a more or less complex joined query that brings back a full set of data rather than parceling out the requests in small pieces.
Using a lazy connection is probably a good idea, since you may not need the database connection at all for some script executions.
On the other hand, once it's open, leave it open, and either close it explicitly as the script ends, or allow PHP to clean up the connection - having an open connection isn't going to harm anything, and you don't want to incur the unnecessary overhead of checking and re-establishing a connection if you are querying the database a second time.

Categories