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 <i...@member.fsf.org>:
> 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 Саша Стаменковић <umpir...@gmail.com>:
>> 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 <i...@member.fsf.org>
>> 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 <i...@member.fsf.org>:
>>> > Forgotten trace and profiler info.
>>> >
>>> > 2010/5/25 Aleksey Zapparov <i...@member.fsf.org>:
>>> >> 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 Саша Стаменковић <umpir...@gmail.com>:
>>> >>> 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, Саша Стаменковић
>>> >>> <umpir...@gmail.com>
>>> >>> wrote:
>>> >>>>
>>> >>>> Cache can be the temporary fix.
>>> >>>>
>>> >>>> Regards,
>>> >>>> Saša Stamenković
>>> >>>>
>>> >>>>
>>> >>>> On Tue, May 25, 2010 at 11:35 AM, Саша Стаменковић
>>> >>>> <umpir...@gmail.com>
>>> >>>> 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, Саша Стаменковић
>>> >>>>> <umpir...@gmail.com>
>>> >>>>> 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
>>> >>>>>> <i...@member.fsf.org>
>>> >>>>>> 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 <i...@member.fsf.org>:
>>> >>>>>>> > 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 Саша Стаменковић <umpir...@gmail.com>:
>>> >>>>>>> >> 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.
>>> >>>>>>> >> <whist...@googlemail.com>
>>> >>>>>>> >> 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: zappa...@jabber.ru
>>> >>>>>>> >
>>> >>>>>>> > *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: zappa...@jabber.ru
>>> >>>>>>>
>>> >>>>>>> *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: zappa...@jabber.ru
>>> >>
>>> >> *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: zappa...@jabber.ru
>>> >
>>> > *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: zappa...@jabber.ru
>>>
>>> *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: zappa...@jabber.ru
>
> *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: zappa...@jabber.ru

*Origin: Happy Hacking!

Reply via email to