How CodeIgniter close db connections? |
I'm wondering how CodeIgniter close db connections. In the doc, it says "CodeIgniter intelligently takes care of closing your database connections". But how does CodeIgniter do this? Seems I didn't find the db driver's "close" method get called in CodeIgniter 3.0.3 source code.
I've also posted in StackOverflow: http://stackoverflow.com/questions/43922...onnections Thanks!
There is a db->close() method. In a PHP environment that is not using persistent connections there is no real need to call it. For MySQL in particular, all open non-persistent MySQL connections and result sets are automatically destroyed when a PHP script finishes its execution. Which in CodeIgniter happens right after the controller method finishes. So you could call $this->db->close(); in some model or in a controller. But all you would accomplish is freeing up the connection resources a few microseconds earlier than if you let script execution finish.
If you have a high-demand situation and are therefore using persistent connections that is a different story. http://php.net/manual/en/features.persis...ctions.php (05-15-2017, 02:44 PM)dave friend Wrote: There is a db->close() method. In a PHP environment that is not using persistent connections there is no real need to call it. For MySQL in particular, all open non-persistent MySQL connections and result sets are automatically destroyed when a PHP script finishes its execution. Which in CodeIgniter happens right after the controller method finishes. So you could call $this->db->close(); in some model or in a controller. But all you would accomplish is freeing up the connection resources a few microseconds earlier than if you let script execution finish. My application structure:
Quote:Message: mysqli::real_connect(): (42000/1203): User <user> already has more than 'max_user_connections' active connections Now, will CI close database connections after finishing execution of Module A script or after finishing individual execution of Modules B to M scripts (which are actually creating database connections). Logically (and "intelligently"), it should be the latter. The connections in cross-database joins within CI are not clear. How are they opened, managed, and closed? Can those connections cause "max_user_connections" error in MySQL on live server where allowed limit is 10-15? Any help is appreciated. Thanks.
CI establishes the database connection when the database is loaded either through inclusion in autoload.php or by calling
PHP Code: $this->load->database(); If that line is called more than once nothing will change. Except under special circumstances the database class is only loaded once establishing one connection. That connection will continue to be used throughout the execution of the current instance of CI. It does not matter how many models are loaded or how many database operations are performed the same connection will be used. As mentioned earlier, all open connections and result sets are automatically destroyed (closed) when a PHP script finishes executing. Additional connections can be created, but that requires providing optional parameters to load->database(). See the documentation for details. This use is the "special circumstances" I mentioned above. I assume you are using this feature to make cross-database queries. Your 'max_user_connections' troubles might be related to making calls to load->database() with the same parameters. In other words, if you are doing something like this within a model to use more than one db. PHP Code: $DB1 = $this->load->database('group_one', TRUE); If you make the same calls again in a different model (or module?) that might be the source of your problem. When the model is done with its job you should probably call PHP Code: $DB1->close(); Maybe making the connections ($DB1, $DB2) properties of the controller so they can be utilized in any model or library loaded would be helpful. I have no knowledge on how using HMVC affects the usefulness of this idea.
Thank you dave friend for the reply. I'll look at your proposed solution (since it's a large application and I'll have to really dig deep to implement this correctly). Meanwhile, can you please give some feedback on the following.
PHP Code: $this->db->select()
Quote:Your 'max_user_connections' troubles might be related to making calls to load->database() with the same parameters.do you think, (a) the multiple load->database() calls with same parameters even for single $DB (group) object can cause the 'max_user_connections' problem? (b) the method used for cross-database joins can cause the 'max_user_connections' problem? (CI's handling of connections made through this method, in presence of groups, is also unclear). Logically, I'd think that since multiple databases are supported in CI through groups, and each group can only be accessed through load->database('group'):
(05-24-2017, 01:16 PM)xuhaib Wrote: do you think, I assume that you literally mean PHP Code: $this->load->database('group'); PHP Code: $this->load->database('group', TRUE); If you do mean it the second way then you probably already understand what I'm about to say and I apologize. I don't mean to talk down to you. If the load uses the second argument e.g. $this->load->database('group', TRUE); then yes, I think it can cause the 'max_user_connections' problem. When the second argument is TRUE the loader returns a CI_DB instance (a.k.a. "connection", a.k.a. "resource") whether the 'group' has been loaded previously or not. Once opened the connection will remain open until the framework finishes executing. In other words, until the controller returns and the CI shutdown routines finish. (05-24-2017, 01:16 PM)xuhaib Wrote: (b) the method used for cross-database joins can cause the 'max_user_connections' problem? (CI's handling of connections made through this method, in presence of groups, is also unclear). No, I don't think that is related. Making queries requires an open connection but does not create a connection. (05-24-2017, 01:16 PM)xuhaib Wrote: Logically, I'd think that since multiple databases are supported in CI through groups, and each group can only be accessed through load->database('group'): Once a call to $this->load->database('group') is made (no second argument) any additional calls (with no second argument) are ignored. The loader returns FALSE and nothing changes. In other words, the CI superobject $db is the same resource that was established earlier and is accessed via $this->db. The first argument - the group name - has no effect on this behavior. Only by passing TRUE to the second argument will an additional connection be created. (05-24-2017, 01:16 PM)xuhaib Wrote: That is true. But after the autoload any calls to $this->load->database('group'); will do nothing without setting the second argument to TRUE. If you do that, you have to capture the return from the loader in order to use that resource. (05-24-2017, 01:16 PM)xuhaib Wrote: If in a model in order to connect to and use a second database you do this. PHP Code: public function get_something() It is logical to assume that since $model_db is going out of scope when the method returns that the resource will be destroyed. But it is not! This is because of the way the MySQL handles resources in PHP. To restate what I said before in a slightly different way: Once created MySQL resources will remain valid until the framework finishes executing. However, you would be hard pressed to reuse the resource since you have lost the reference to it. In order to free the resources opened in the get_something() method you have to do this PHP Code: public function get_something() I have tested this assertion while monitoring resources via phpMyAdmin. Trust me, it's true. The moral of the story is that you have to explicitly close a database in order to free the resources. There a lots of different ways you could handle multiple database loads. Loading and closing the database in a method as shown above may be easiest and safest but could result in a lot of redundant code. Each method would have to do the same. If you create a class property in the model that is set in __construct() you will probably need a method to cleanup and to run that after you're done with the model. PHP Code: class Othermodel extends CI_Model You would probably want to make sure that $this->model_db is set before trying to use it. So more work would be needed to fill out the above class. But you get the idea. Using that model in a controller might go like this PHP Code: $this->load->model('othermodel'); Hope this helps.
Thanks again dave for a detailed reply. Both your replies are informative and understood. I agree with your explanation. But still not so confident about CI's logic behind this behavior.
CI docs state that: Quote:1. To choose a specific group from your config file you can do this: Now, consider this simplest case for multiple databases:
On that note, (and similarly pretty scarce reference material available anywhere), can you please give some suggestions on correctly implementing db_select() if you have had any experience with it. I feel that using db_select() will be the most efficient solution at this point if all databases are moved to same configuration. Thank you again for your time and insight. |
Welcome Guest, Not a member yet? Register Sign In |