Oh my, if I would have no limits on shared hosting, we would never find out!
Switched to PDO. Спасибо Алексей! Regards, Saša Stamenković On Tue, May 25, 2010 at 10:01 PM, Aleksey Zapparov <[email protected]>wrote: > Suddenly I have changed my mind ;)) It's not a problem of framework at all. > It's a problem in mysqli itself. Seems like my browser cached data, so I've > found that mysqli.php (from previous message) is hanging server too (!) > > Anyway I think Zend_Db_Statement_Mysqli needs a simple destructor: > > public function __destruct() > { > $this->close(); > } > > Unfortunately it will not help anyway. I'm going to bug report to PHP as > it's > a problem with mysqli extension. > > > 2010/5/25 Aleksey Zapparov <[email protected]>: > > Yes. You are right! That's the problem and it's not :)) > > > > I have tested it with very dummy test (see attachment mysqli.php.gz) and > > it works like a charm (against stormer provided before). So I have > discovered > > that the problem is in framework. > > > > The problem is that result cursor is never closed. Here's what happens in > > sample application provided by me in one of previous messages. We have > > following code: > > > > $news = new Automobili_Model_Table_News(); > > $news->fetchAll($news->select()); > > > > In other words it can be written like this (to better understand): > > > > /** Zend_Db_Table_Abstract */ > > $news = new Automobili_Model_Table_News(); > > /** Zend_Db_Table_Select */ > > $select = $news->select(); > > > > $news->fetchAll($select); > > > > The most interesting part here is fetchAll() which internally > > calls protected method _fetch() which is clean enough: > > > > 1503 protected function _fetch(Zend_Db_Table_Select $select) > > 1504 { > > 1505 $stmt = $this->_db->query($select); > > 1506 $data = $stmt->fetchAll(Zend_Db::FETCH_ASSOC); > > 1507 return $data; > > 1508 } > > > > Now, what we have here. This code creates a new object ($stmt) of > > Zend_Db_Statement_Mysqli calls it's fetchAll() and returns it's result > > (array of rows). And that's where all problems began. Statement > > grabs results with standard mysqli functions, but it does not close > > cursor automatically! > > > > After I spend another hour trying to implement some easy workarounds, > > I found that there are no "easy" workaround at all. Except making some > > modifications to Zend_Db_Adapter_Mysqli and Zend_Db_Adapter_Statement. > > > > Of course there's one easy workaround (and I'm pretty sure that some of > > developers will say that it's a feature) - you can first, replace that > > small code > > for rows retrievement with something like this: > > > > $news = new Automobili_Model_Table_News(); > > $select = $news->select(); > > $stmt = $news->getAdapter()->query($select); > > > > $this->view->assign('rows', $stmt->fetchAll(Zend_Db::FETCH_OBJ)); > > $stmt->closeCursor(); > > $stmt->close(); > > > > and then add postDispatch hook with closing db handler: > > > > Zend_Db_Table_Abstract::getDefaultAdapter()->closeConnection(); > > > > > > Unfortunatelly even this caused sample application (from previous post) > > to hang server up after 130 requests. I'm gonna try to make some changes > > to the Zend_Db_Adapter_Mysqli and Zend_Db_Statement_Mysqli today > > or tomorrow and will share my investigation results :)) > > > > > > 2010/5/25 Саша Стаменковић <[email protected]>: > >> Zend_Db_Statement in setFetchMode() calls $this->closeCursor(); only in > >> default case for $mode, why not in other cases?! > >> > >> Regards, > >> Saša Stamenković > >> > >> > >> On Tue, May 25, 2010 at 4:37 PM, Aleksey Zapparov <[email protected]> > >> wrote: > >>> > >>> I'll prepare a dummy test with direct mysqli opertating - without using > >>> Zend Framework at all - just to make sure that it's not a framework's > >>> error. I'm pretty sure it's not but still want to have solid > approvements. > >>> > >>> > >>> 2010/5/25 Aleksey Zapparov <[email protected]>: > >>> > Forgotten trace and profiler info. > >>> > > >>> > 2010/5/25 Aleksey Zapparov <[email protected]>: > >>> >> Hello everybody again, > >>> >> > >>> >> Unfortunately I forgot to add CC to group, so we were discussing > >>> >> problem > >>> >> with Саша privately :)) But he mentioned that there left only two of > >>> >> us, > >>> >> so I'm repeating abridged summary of discussion. > >>> >> > >>> >> First of all, I successfully repeated error mentioned by Саша. It do > >>> >> not > >>> >> related with database engine (so I was able to successfully repeat > it > >>> >> with both MyISAM and InnoDB). > >>> >> > >>> >> I was keeping track of connections, while storming a server. And > indeed > >>> >> there were only ONE connection to the database. But after a 'storm' > (in > >>> >> fact 5-10 rapidly repeated requests was enough) server became down. > >>> >> I'll > >>> >> explain in details a little bit later. Here's dummy stormer in Ruby > I > >>> >> was using to reproduce an error: > >>> >> > >>> >> > >>> >> require 'rubygems' > >>> >> require 'httpclient' > >>> >> > >>> >> client = HTTPClient.new > >>> >> uri = 'http://localhost/zfw' > >>> >> status = 'ACTIVE' > >>> >> > >>> >> (1..128).each do > >>> >> status = ('ACTIVE' == status) ? 'INACTIVE' : 'ACTIVE' > >>> >> client.post(uri, { 'status' => status } > >>> >> end > >>> >> > >>> >> > >>> >> So after running this stormer, assuming 'http://localhost/zfw' is > an > >>> >> index action of index controller of our application which selects > rows > >>> >> from database (there were only 32 rows total in database on > testing), > >>> >> index action started throw Zend_Db_Adapter_Mysqli_Exception all the > >>> >> time (until I have restarted Apache2 server). This exception had > empty > >>> >> message. Here's a trace: > >>> >> > >>> >> #0 /var/www/zfw-app/library/Zend/Db/Adapter/Abstract.php(304): > >>> >> Zend_Db_Adapter_Mysqli->_connect() > >>> >> #1 /var/www/zfw-app/library/Zend/Db/Adapter/Mysqli.php(194): > >>> >> Zend_Db_Adapter_Abstract->getConnection() > >>> >> #2 /var/www/zfw-app/library/Zend/Db/Table/Abstract.php(823): > >>> >> Zend_Db_Adapter_Mysqli->describeTable('automobili_news', NULL) > >>> >> #3 /var/www/zfw-app/library/Zend/Db/Table/Abstract.php(862): > >>> >> Zend_Db_Table_Abstract->_setupMetadata() > >>> >> #4 /var/www/zfw-app/library/Zend/Db/Table/Abstract.php(969): > >>> >> Zend_Db_Table_Abstract->_setupPrimaryKey() > >>> >> #5 /var/www/zfw-app/library/Zend/Db/Table/Select.php(100): > >>> >> Zend_Db_Table_Abstract->info() > >>> >> #6 /var/www/zfw-app/library/Zend/Db/Table/Select.php(78): > >>> >> Zend_Db_Table_Select->setTable(Object(Automobili_Model_Table_News)) > >>> >> #7 /var/www/zfw-app/library/Zend/Db/Table/Abstract.php(1005): > >>> >> > Zend_Db_Table_Select->__construct(Object(Automobili_Model_Table_News)) > >>> >> #8 /var/www/zfw-app/application/controllers/IndexController.php(14): > >>> >> Zend_Db_Table_Abstract->select() > >>> >> #9 /var/www/zfw-app/library/Zend/Controller/Action.php(513): > >>> >> IndexController->indexAction() > >>> >> #10 > >>> >> > /var/www/zfw-app/library/Zend/Controller/Dispatcher/Standard.php(289): > >>> >> Zend_Controller_Action->dispatch('indexAction') > >>> >> #11 /var/www/zfw-app/library/Zend/Controller/Front.php(954): > >>> >> > >>> >> > Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http), > >>> >> Object(Zend_Controller_Response_Http)) > >>> >> #12 > >>> >> > /var/www/zfw-app/library/Zend/Application/Bootstrap/Bootstrap.php(97): > >>> >> Zend_Controller_Front->dispatch() > >>> >> #13 /var/www/zfw-app/library/Zend/Application.php(366): > >>> >> Zend_Application_Bootstrap_Bootstrap->run() > >>> >> #14 /var/www/zfw-app/public/index.php(26): Zend_Application->run() > >>> >> #15 {main} > >>> >> > >>> >> > >>> >> For those who are interested in details I have attached an xdebug > >>> >> trace as an attachment (trace.xt.gz) and xdebug profiler data > >>> >> (cachegrind.out.gz). > >>> >> > >>> >> After all I have switched config to use pdo_mysql instead of mysqli > and > >>> >> was able to run my (previously described) stormer without any > problems > >>> >> even with 1024 requests. So I guess there's something wrong with > mysqli > >>> >> adapter (of PHP). > >>> >> > >>> >> > >>> >> 2010/5/25 Саша Стаменковић <[email protected]>: > >>> >>> Zend_Db_Statement ин setFetchMode() calls $this->closeCursor(); > only > >>> >>> in > >>> >>> default case fro $mode ?! > >>> >>> > >>> >>> Regards, > >>> >>> Saša Stamenković > >>> >>> > >>> >>> > >>> >>> On Tue, May 25, 2010 at 11:40 AM, Саша Стаменковић > >>> >>> <[email protected]> > >>> >>> wrote: > >>> >>>> > >>> >>>> Cache can be the temporary fix. > >>> >>>> > >>> >>>> Regards, > >>> >>>> Saša Stamenković > >>> >>>> > >>> >>>> > >>> >>>> On Tue, May 25, 2010 at 11:35 AM, Саша Стаменковић > >>> >>>> <[email protected]> > >>> >>>> wrote: > >>> >>>>> > >>> >>>>> I found where the problem was! > >>> >>>>> $newsTable->publishNews($ids); > >>> >>>>> foreach ($newsTable->fetchNewsByIds($ids) as $news) { > >>> >>>>> $news->publishOnTwitter(); > >>> >>>>> } > >>> >>>>> Row have this publish on twitter method, which shouldn't have > >>> >>>>> nothing to > >>> >>>>> do with the problem - WRONG! It has. When I post it on twitter, a > >>> >>>>> great > >>> >>>>> amount of traffic is generated, people are opening concrete news > and > >>> >>>>> break > >>> >>>>> my limit of 15 connections. > >>> >>>>> Looks like I need more connections, heh. > >>> >>>>> Regards, > >>> >>>>> Saša Stamenković > >>> >>>>> > >>> >>>>> > >>> >>>>> On Tue, May 25, 2010 at 10:57 AM, Саша Стаменковић > >>> >>>>> <[email protected]> > >>> >>>>> wrote: > >>> >>>>>> > >>> >>>>>> BTW, my limit is not > >>> >>>>>> mysqli.max_links = 15 > >>> >>>>>> its a property of mysql.user table, MAX_USER_CONNECTIONS. > >>> >>>>>> http://dev.mysql.com/doc/refman/5.1/en/user-resources.html > >>> >>>>>> > >>> >>>>>> Regards, > >>> >>>>>> Saša Stamenković > >>> >>>>>> > >>> >>>>>> > >>> >>>>>> On Mon, May 24, 2010 at 11:44 PM, Aleksey Zapparov > >>> >>>>>> <[email protected]> > >>> >>>>>> wrote: > >>> >>>>>>> > >>> >>>>>>> Hello, > >>> >>>>>>> > >>> >>>>>>> Was not able to wait until tomorow to test on FreeBSD as it was > >>> >>>>>>> really > >>> >>>>>>> interesting for will it work or not. And it does. Here's mysqli > >>> >>>>>>> config > >>> >>>>>>> of my > >>> >>>>>>> php.ini on FreeBSD: > >>> >>>>>>> > >>> >>>>>>> mysqli.max_links = 15 > >>> >>>>>>> mysqli.default_port = 3306 > >>> >>>>>>> mysqli.default_socket = > >>> >>>>>>> mysqli.default_host = > >>> >>>>>>> mysqli.default_user = > >>> >>>>>>> mysqli.default_pw = > >>> >>>>>>> mysqli.reconnect = Off > >>> >>>>>>> > >>> >>>>>>> You can see it's working at: http://sandbox.ixti.ru/zfw/ (it > will > >>> >>>>>>> be > >>> >>>>>>> available > >>> >>>>>>> at least until 27th of May 2010). > >>> >>>>>>> > >>> >>>>>>> > >>> >>>>>>> 2010/5/24 Aleksey Zapparov <[email protected]>: > >>> >>>>>>> > Hello, > >>> >>>>>>> > > >>> >>>>>>> > I guess you are doing something wrong. I have just build up a > >>> >>>>>>> > little > >>> >>>>>>> > app from > >>> >>>>>>> > scratch with zf tool (attachment app.tar.gz) which simply > >>> >>>>>>> > "batch" > >>> >>>>>>> > updates > >>> >>>>>>> > 32 rows with new status - very dumy logic in controller: > >>> >>>>>>> > > >>> >>>>>>> > $news = new Automobili_Model_Table_News(); > >>> >>>>>>> > $ids = range(1,32); > >>> >>>>>>> > > >>> >>>>>>> > $news->update( > >>> >>>>>>> > array('status' => $status), > >>> >>>>>>> > $news->getAdapter()->quoteInto('id IN (?)', $ids, > >>> >>>>>>> > Zend_Db::INT_TYPE) > >>> >>>>>>> > ); > >>> >>>>>>> > > >>> >>>>>>> > And it works good for me at least on my GNU/Linux. > >>> >>>>>>> > Here's my php.ini (section of MySQLi): > >>> >>>>>>> > > >>> >>>>>>> > mysqli.max_persistent = 15 > >>> >>>>>>> > mysqli.allow_persistent = Off > >>> >>>>>>> > mysqli.max_links = 15 > >>> >>>>>>> > mysqli.cache_size = 2000 > >>> >>>>>>> > mysqli.default_port = 3306 > >>> >>>>>>> > mysqli.default_socket = > >>> >>>>>>> > mysqli.default_host = > >>> >>>>>>> > mysqli.default_user = > >>> >>>>>>> > mysqli.default_pw = > >>> >>>>>>> > mysqli.reconnect = Off > >>> >>>>>>> > > >>> >>>>>>> > > >>> >>>>>>> > I have a FreeBSD running host so tomorow I'm gonna check this > >>> >>>>>>> > app > >>> >>>>>>> > against > >>> >>>>>>> > it. Anyway you can try my dummy app by yourself (I've removed > >>> >>>>>>> > some > >>> >>>>>>> > portion > >>> >>>>>>> > from your News table class (which was referring to another > >>> >>>>>>> > model) to > >>> >>>>>>> > be able > >>> >>>>>>> > run this code). > >>> >>>>>>> > > >>> >>>>>>> > Attached files are: > >>> >>>>>>> > app.tar.gz - Application itself > >>> >>>>>>> > dump.sql.gz - MySQL dump of table (I have used to test) > >>> >>>>>>> > > >>> >>>>>>> > > >>> >>>>>>> > 2010/5/24 Саша Стаменковић <[email protected]>: > >>> >>>>>>> >> Okay, I'm using one connection, one db, one adapter, but > still, > >>> >>>>>>> >> I > >>> >>>>>>> >> have > >>> >>>>>>> >> problems. I'm pretty sure I'm using it right, because I'm > using > >>> >>>>>>> >> it > >>> >>>>>>> >> like it > >>> >>>>>>> >> says in the doc. > >>> >>>>>>> >> The problem is, I can exec up to 15 queries in the row, and > >>> >>>>>>> >> this > >>> >>>>>>> >> quoteInto > >>> >>>>>>> >> with array param is hitting my limits. > >>> >>>>>>> >> I can send you my code on private mail Thomas. > >>> >>>>>>> >> > >>> >>>>>>> >> Regards, > >>> >>>>>>> >> Saša Stamenković > >>> >>>>>>> >> > >>> >>>>>>> >> > >>> >>>>>>> >> On Mon, May 24, 2010 at 9:27 PM, Thomas D. > >>> >>>>>>> >> <[email protected]> > >>> >>>>>>> >> wrote: > >>> >>>>>>> >>> > >>> >>>>>>> >>> Hi, > >>> >>>>>>> >>> > >>> >>>>>>> >>> Саша Стаменковић wrote: > >>> >>>>>>> >>> > Sure, when you have unlimited number of db operation over > >>> >>>>>>> >>> > a period of time. I'll come up with my own offline > quoting. > >>> >>>>>>> >>> > >>> >>>>>>> >>> Seems like you are missing one fact all over the time: > >>> >>>>>>> >>> That quoting would use a connection to a database server, > >>> >>>>>>> >>> isn't a > >>> >>>>>>> >>> problem, > >>> >>>>>>> >>> because Zend_Db_* would use one connection across every > >>> >>>>>>> >>> component. > >>> >>>>>>> >>> Only if > >>> >>>>>>> >>> you are working with multiple databases, it might be a > >>> >>>>>>> >>> problem, > >>> >>>>>>> >>> because you > >>> >>>>>>> >>> would have one adapter per database (=nAdapter * 1 > Connection > >>> >>>>>>> >>> = n > >>> >>>>>>> >>> connections)... > >>> >>>>>>> >>> > >>> >>>>>>> >>> So again: > >>> >>>>>>> >>> When you are working with just *one* database, everything > >>> >>>>>>> >>> should > >>> >>>>>>> >>> work > >>> >>>>>>> >>> fine. > >>> >>>>>>> >>> If not, *you* are doing something wrong. > >>> >>>>>>> >>> > >>> >>>>>>> >>> Doing your own quoting is everything but not safe. You > should > >>> >>>>>>> >>> use > >>> >>>>>>> >>> the > >>> >>>>>>> >>> adapter's escape function, if your application should be > safe. > >>> >>>>>>> >>> > >>> >>>>>>> >>> > >>> >>>>>>> >>> -- > >>> >>>>>>> >>> Regards, > >>> >>>>>>> >>> Thomas > >>> >>>>>>> >>> > >>> >>>>>>> >>> > >>> >>>>>>> >> > >>> >>>>>>> >> > >>> >>>>>>> > > >>> >>>>>>> > > >>> >>>>>>> > > >>> >>>>>>> > -- > >>> >>>>>>> > Sincerely yours, > >>> >>>>>>> > Aleksey V. Zapparov A.K.A. ixti > >>> >>>>>>> > FSF Member #7118 > >>> >>>>>>> > Mobile Phone: +34 617 179 344 > >>> >>>>>>> > Homepage: http://www.ixti.ru > >>> >>>>>>> > JID: [email protected] > >>> >>>>>>> > > >>> >>>>>>> > *Origin: Happy Hacking! > >>> >>>>>>> > > >>> >>>>>>> > >>> >>>>>>> > >>> >>>>>>> > >>> >>>>>>> -- > >>> >>>>>>> Sincerely yours, > >>> >>>>>>> Aleksey V. Zapparov A.K.A. ixti > >>> >>>>>>> FSF Member #7118 > >>> >>>>>>> Mobile Phone: +34 617 179 344 > >>> >>>>>>> Homepage: http://www.ixti.ru > >>> >>>>>>> JID: [email protected] > >>> >>>>>>> > >>> >>>>>>> *Origin: Happy Hacking! > >>> >>>>>> > >>> >>>>> > >>> >>>> > >>> >>> > >>> >>> > >>> >> > >>> >> > >>> >> > >>> >> -- > >>> >> Sincerely yours, > >>> >> Aleksey V. Zapparov A.K.A. ixti > >>> >> FSF Member #7118 > >>> >> Mobile Phone: +34 617 179 344 > >>> >> Homepage: http://www.ixti.ru > >>> >> JID: [email protected] > >>> >> > >>> >> *Origin: Happy Hacking! > >>> >> > >>> > > >>> > > >>> > > >>> > -- > >>> > Sincerely yours, > >>> > Aleksey V. Zapparov A.K.A. ixti > >>> > FSF Member #7118 > >>> > Mobile Phone: +34 617 179 344 > >>> > Homepage: http://www.ixti.ru > >>> > JID: [email protected] > >>> > > >>> > *Origin: Happy Hacking! > >>> > > >>> > >>> > >>> > >>> -- > >>> Sincerely yours, > >>> Aleksey V. Zapparov A.K.A. ixti > >>> FSF Member #7118 > >>> Mobile Phone: +34 617 179 344 > >>> Homepage: http://www.ixti.ru > >>> JID: [email protected] > >>> > >>> *Origin: Happy Hacking! > >> > >> > > > > > > > > -- > > Sincerely yours, > > Aleksey V. Zapparov A.K.A. ixti > > FSF Member #7118 > > Mobile Phone: +34 617 179 344 > > Homepage: http://www.ixti.ru > > JID: [email protected] > > > > *Origin: Happy Hacking! > > > > > > -- > Sincerely yours, > Aleksey V. Zapparov A.K.A. ixti > FSF Member #7118 > Mobile Phone: +34 617 179 344 > Homepage: http://www.ixti.ru > JID: [email protected] > > *Origin: Happy Hacking! >
