Hi,
I'v implemented new_link paramater (as in mysql_connect) for
mysql_pconnect().
Since client_flags were added to those functions in 4.3.x the parameter is
4th in mysql_connect() and 5th in mysql_pconnect().
When new_link is true when connecting to mysql database with
mysql_pconnect() two things happen:
1) you always get unique connection to database (no matter what hostname,
username or password you supplied. When connecting the code will check if
there is an idle connection to server and when found that connection will
be reused. When no connection found, new connection will be created and
registered for future use within same child(/thread?).
2) when new_link is true, mysql_pconnect won't waste your connections to
mysql servers like it has been doing up to day. This is achieved by using
mysql_change_user() API call which is available starting from MySQL 3.23.3.
This patch should be great news for people with many virtual servers and
different mysql usernames/password for each user using their service.
---
With this patch and new_link 'true' connection usage to one server will be
maximum of
[Apache MaxClients conf option]*[different mysql hostname/port combinations]
That means when MaxClients=50 and max_persistent=1
you will get no more that 50 real connection hovering around to same mysql
server.
---
Without this patch it is (or new_link 'false'):
[Apache MaxClients conf option]*[different mysql hostname/port/username
password combinations]
This means that when MaxClients=50 and max_persistent=1 and have 50 clients
using mysql_pconnect() you could have maximum of 2500!!! connections to one
server. In reality it is not as bad but not good either.
--
So I think this should patch would be nice to have included in future PHP
releases.
I'm not sure I made good/correct/effective use of PHP/Zend internal
functions. I hope so. If not please point out what's wrong and I'll try to
fix.
Oh, this patch is against PHP4.3.3. Go to ext/mysql dir and 'patch -p1'.
Lenar
Common subdirectories: old/libmysql and new/libmysql
diff -ub old/php_mysql.c new/php_mysql.c
--- old/php_mysql.c 2003-08-08 16:36:44.000000000 +0300
+++ new/php_mysql.c 2003-09-14 19:40:40.000000000 +0300
@@ -90,6 +90,10 @@
#define MYSQL_HAS_YEAR
#endif
+#if MYSQL_VERSION_ID >= 32303
+#define MYSQL_HAS_CHANGE_USER
+#endif
+
#define MYSQL_ASSOC 1<<0
#define MYSQL_NUM 1<<1
#define MYSQL_BOTH (MYSQL_ASSOC|MYSQL_NUM)
@@ -420,6 +424,10 @@
*/
PHP_RINIT_FUNCTION(mysql)
{
+#ifdef MYSQL_HAS_CHANGE_USER
+ ALLOC_HASHTABLE(MySG(inuse_list));
+ zend_hash_init(MySG(inuse_list), 1, NULL, NULL, 0);
+#endif
MySG(default_link)=-1;
MySG(num_links) = MySG(num_persistent);
/* Reset connect error/errno on every request */
@@ -442,10 +450,13 @@
php_error_docref("function.mysql-free-result" TSRMLS_CC, E_WARNING, tmp);
}
}
-
if (MySG(connect_error)!=NULL) {
efree(MySG(connect_error));
}
+#ifdef MYSQL_HAS_CHANGE_USER
+ zend_hash_destroy(MySG(inuse_list));
+ FREE_HASHTABLE(MySG(inuse_list));
+#endif
return SUCCESS;
}
/* }}} */
@@ -501,6 +512,7 @@
zval **z_host=NULL, **z_user=NULL, **z_passwd=NULL, **z_new_link=NULL, **z_client_flags=NULL;
zend_bool free_host=0, new_link=0;
long connect_timeout;
+ list_entry *inuse_le=NULL;
connect_timeout = MySG(connect_timeout);
@@ -513,9 +525,6 @@
}
host_and_port=passwd=NULL;
user=php_get_current_user();
- hashed_details_length = strlen(user)+5+3;
- hashed_details = (char *) emalloc(hashed_details_length+1);
- sprintf(hashed_details, "mysql__%s_", user);
client_flags = CLIENT_INTERACTIVE;
} else {
host_and_port = MySG(default_host);
@@ -575,9 +584,16 @@
}
break;
case 5: {
+ if (persistent) {
+ if (zend_get_parameters_ex(5, &z_host, &z_user, &z_passwd, &z_client_flags, &z_new_link) == FAILURE) {
+ MYSQL_DO_CONNECT_RETURN_FALSE();
+ }
+ }
+ else {
if (zend_get_parameters_ex(5, &z_host, &z_user, &z_passwd, &z_new_link, &z_client_flags) == FAILURE) {
MYSQL_DO_CONNECT_RETURN_FALSE();
}
+ }
convert_to_string_ex(z_user);
convert_to_string_ex(z_passwd);
convert_to_boolean_ex(z_new_link);
@@ -610,11 +626,36 @@
}
}
}
+ }
+ if (!MySG(allow_persistent)) {
+ persistent=0;
+ }
+
+#ifdef MYSQL_HAS_CHANGE_USER
+ if (!(new_link && persistent)) {
+#endif
+ if (PG(sql_safe_mode)) {
+ hashed_details_length = strlen(user)+5+3;
+ hashed_details = (char *) emalloc(hashed_details_length+1);
+ sprintf(hashed_details, "mysql__%s_", user);
+ } else {
hashed_details_length = sizeof("mysql___")-1 + strlen(SAFE_STRING(host_and_port))+strlen(SAFE_STRING(user))+strlen(SAFE_STRING(passwd));
hashed_details = (char *) emalloc(hashed_details_length+1);
sprintf(hashed_details, "mysql_%s_%s_%s", SAFE_STRING(host_and_port), SAFE_STRING(user), SAFE_STRING(passwd));
}
+#ifdef MYSQL_HAS_CHANGE_USER
+ } else {
+ long count = 0;
+
+ if(zend_hash_find(MySG(inuse_list), SAFE_STRING(host_and_port), strlen(SAFE_STRING(host_and_port))+1, (void **) &inuse_le)==SUCCESS) {
+ count = (long) inuse_le->ptr;
+ }
+ hashed_details_length = sizeof("mysqlp__")-1 + strlen(SAFE_STRING(host_and_port)) + 10;
+ hashed_details = (char *) emalloc(hashed_details_length+1);
+ sprintf(hashed_details, "mysqlp_%s_%ld", SAFE_STRING(host_and_port), count);
+ }
+#endif
/* We cannot use mysql_port anymore in windows, need to use
* mysql_real_connect() to set the port.
@@ -641,9 +682,6 @@
mysql_port = port;
#endif
- if (!MySG(allow_persistent)) {
- persistent=0;
- }
if (persistent) {
list_entry *le;
@@ -694,10 +732,27 @@
efree(hashed_details);
MYSQL_DO_CONNECT_RETURN_FALSE();
}
+#ifdef MYSQL_CHANGE_USER
+ if(new_link) {
+ if(inuse_le) { /* increase in use count for this host_and_port */
+ ((long)inuse_le->ptr)++;
+ } else {
+ list_entry new_inuse_le;
+
+ ((long) new_inuse_le.ptr) = 1; /* in use count */
+ if (zend_hash_update(MySG(inuse_list), SAFE_STRING(host_and_port), strlen(SAFE_STRING(host_and_port))+1, (void *) &new_inuse_le, sizeof(list_entry), NULL)==FAILURE) {
+ free(mysql);
+ efree(hashed_details);
+ MYSQL_DO_CONNECT_RETURN_FALSE();
+ }
+ }
+ }
+#endif
MySG(num_persistent)++;
MySG(num_links)++;
} else { /* The link is in our list of persistent connections */
if (Z_TYPE_P(le) != le_plink) {
+ efree(hashed_details);
MYSQL_DO_CONNECT_RETURN_FALSE();
}
/* ensure that the link did not die */
@@ -724,6 +779,19 @@
MYSQL_DO_CONNECT_RETURN_FALSE();
}
}
+#ifdef MYSQL_HAS_CHANGE_USER
+ else {
+ if(new_link && mysql_change_user(le->ptr, user, passwd, NULL)) {
+ if (MySG(connect_error)!=NULL) efree(MySG(connect_error));
+ MySG(connect_error)=estrdup(mysql_error(&((php_mysql_conn *)le->ptr)->conn));
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", MySG(connect_error));
+ MySG(connect_errno)=mysql_errno(&((php_mysql_conn *)le->ptr)->conn);
+ efree(hashed_details);
+ MYSQL_DO_CONNECT_RETURN_FALSE();
+ }
+ }
+#endif
+
#if MYSQL_VERSION_ID < 32231
signal(SIGPIPE, handler);
#endif
diff -ub old/php_mysql.h new/php_mysql.h
--- old/php_mysql.h 2002-12-31 18:35:00.000000000 +0200
+++ new/php_mysql.h 2003-09-14 19:11:49.000000000 +0300
@@ -105,6 +105,7 @@
long connect_timeout;
long result_allocated;
long trace_mode;
+ HashTable *inuse_list;
ZEND_END_MODULE_GLOBALS(mysql)
#ifdef ZTS
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php