Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:36684 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 14097 invoked from network); 30 Mar 2008 12:30:30 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 30 Mar 2008 12:30:30 -0000 Received: from [127.0.0.1] ([127.0.0.1:22501]) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ECSTREAM id 8C/C4-14120-6E78FE74 for ; Sun, 30 Mar 2008 07:30:30 -0500 Authentication-Results: pb1.pair.com header.from=php.list@daevel.net; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=php.list@daevel.net; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain daevel.net designates 80.248.217.131 as permitted sender) X-PHP-List-Original-Sender: php.list@daevel.net X-Host-Fingerprint: 80.248.217.131 carthago.dv.daevel.fr Linux 2.6 Received: from [80.248.217.131] ([80.248.217.131:35358] helo=carthago.dv.daevel.fr) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 0D/83-14120-B3A7FE74 for ; Sun, 30 Mar 2008 06:32:12 -0500 Received: from luuna.daevel.net ([82.67.25.170] helo=[192.168.1.50]) by carthago.dv.daevel.fr with esmtpsa (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.63) (envelope-from ) id 1Jfvlg-0002qq-7q for internals@lists.php.net; Sun, 30 Mar 2008 13:32:08 +0200 Message-ID: <47EF7A6A.2050301@daevel.net> Date: Sun, 30 Mar 2008 13:32:58 +0200 User-Agent: Mozilla-Thunderbird 2.0.0.9 (X11/20080109) MIME-Version: 1.0 To: internals@lists.php.net Content-Type: multipart/mixed; boundary="------------000605000202010508060305" Subject: Add a memory limit in mysql ext From: php.list@daevel.net (Olivier Bonvalet) --------------000605000202010508060305 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Hello, I often host clients which have "bad" PHP/SQL code ; as for example a "select *" + mysql_row_nums on a 200Mo table just to count lines... So I add a little patch to throw a warning in case the result of mysql_query is larger than a specified limit. I use the setting "mysql.min_stored_data_before_warn" in php.ini, and the result is : [30-Mar-2008 04:39:56] PHP Warning: mysql_query() [function.mysql-query]: Your query use too much memory (202636 o) in /path/to/script.php on line 8 This patch seem "usefull" for me as PHP does not report the queries's memory consumption. But maybe it should be done in mysqli and PDO extensions to ? I'm not a "C developper", and the patch use the mysql internal struct, so it's not really "clean". Maybe we can do it differently. Thanks Olivier PS : sorry for my limited english. --------------000605000202010508060305 Content-Type: text/x-patch; name="200-mysql.min_stored_data.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="200-mysql.min_stored_data.patch" diff -aur old/ext/mysql/php_mysql.c new/ext/mysql/php_mysql.c --- old/ext/mysql/php_mysql.c 2006-08-02 12:04:11.000000000 +0200 +++ new/ext/mysql/php_mysql.c 2007-09-10 13:32:13.000000000 +0200 @@ -355,6 +355,7 @@ STD_PHP_INI_ENTRY("mysql.default_socket", NULL, PHP_INI_ALL, OnUpdateStringUnempty, default_socket, zend_mysql_globals, mysql_globals) STD_PHP_INI_ENTRY("mysql.connect_timeout", "60", PHP_INI_ALL, OnUpdateLong, connect_timeout, zend_mysql_globals, mysql_globals) STD_PHP_INI_BOOLEAN("mysql.trace_mode", "0", PHP_INI_ALL, OnUpdateLong, trace_mode, zend_mysql_globals, mysql_globals) + STD_PHP_INI_ENTRY("mysql.min_stored_data_before_warn", "0", PHP_INI_SYSTEM, OnUpdateLong, min_stored_data_before_warn, zend_mysql_globals, mysql_globals) PHP_INI_END() /* }}} */ @@ -1210,13 +1211,21 @@ #endif #endif /* NETWARE */ + /* {{{ php_mysql_do_query_general */ static void php_mysql_do_query_general(zval **query, zval **mysql_link, int link_id, zval **db, int use_store, zval *return_value TSRMLS_DC) { php_mysql_conn *mysql; MYSQL_RES *mysql_result; - + + MYSQL_DATA *data; + MEM_ROOT alloc; + USED_MEM *next; + + long result_size; + + ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, link_id, "MySQL-Link", le_link, le_plink); if (db) { @@ -1283,6 +1292,24 @@ mysql_result=mysql_use_result(&mysql->conn); } else { mysql_result=mysql_store_result(&mysql->conn); + + if( mysql_result && ( MySG(min_stored_data_before_warn) > 0 )) + { + data = mysql_result->data ; + alloc = data->alloc ; + + result_size = alloc.block_size ; + for (next = alloc.used; next; next= next->next ) + { + result_size += ( next->size - next->left ); + } + + if( result_size >= MySG(min_stored_data_before_warn) ) + { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Your query use too much memory (%ld o)", result_size ); + } + } } if (!mysql_result) { if (PHP_MYSQL_VALID_RESULT(&mysql->conn)) { /* query should have returned rows */ diff -aur old/ext/mysql/php_mysql.h new/ext/mysql/php_mysql.h --- old/ext/mysql/php_mysql.h 2006-01-01 13:50:09.000000000 +0100 +++ new/ext/mysql/php_mysql.h 2007-09-10 13:32:13.000000000 +0200 @@ -105,6 +105,7 @@ long connect_timeout; long result_allocated; long trace_mode; + long min_stored_data_before_warn; ZEND_END_MODULE_GLOBALS(mysql) #ifdef ZTS --------------000605000202010508060305--