Discussion:
Saving many Zend_Db_Table_Rows in for loop
Саша Стаменковић
2010-05-17 20:09:21 UTC
Permalink
I have this:

$row = $table->find($id); // Zend_Db_Table
$row->setReadOnly(false);
$row->status = 'ACTIVE';
$row->save();

In for loop. When having for instance 20 iterations, it happends to get

2010-05-17T08:49:07+02:00 ERR (3): exception
'Zend_Db_Adapter_Mysqli_Exception' with message 'User *** already has more
than 'max_user_connections' active connections' in
Zend/Db/Adapter/Mysqli.php:333
Stack trace:
#0 Zend/Db/Adapter/Abstract.php(832): Zend_Db_Adapter_Mysqli->_connect()
#1 Zend/Db/Adapter/Abstract.php(902): Zend_Db_Adapter_Abstract->quote('376',
NULL)
#2 Zend/Db/Select.php(1000): Zend_Db_Adapter_Abstract->quoteInto('table...',
'376', NULL)
#3 Zend/Db/Select.php(475): Zend_Db_Select->_where('table...', '376', NULL,
true)
...

I am on shared FreeBSD hosting.

Is it possible that there is some connection overhead that code like this
can generate?

Regards,
Saša Stamenković
Саша Стаменковић
2010-05-18 11:52:07 UTC
Permalink
Connection is not persistant, maybe I should set 'persistent' => true and
switch from MySQLi to PDO adapter?
*
*
*What is the difference when I use persistant connection?
*
Regards,
Saša Stamenković


On Mon, May 17, 2010 at 10:09 PM, Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>wrote:

> I have this:
>
> $row = $table->find($id); // Zend_Db_Table
> $row->setReadOnly(false);
> $row->status = 'ACTIVE';
> $row->save();
>
> In for loop. When having for instance 20 iterations, it happends to get
>
> 2010-05-17T08:49:07+02:00 ERR (3): exception
> 'Zend_Db_Adapter_Mysqli_Exception' with message 'User *** already has more
> than 'max_user_connections' active connections' in
> Zend/Db/Adapter/Mysqli.php:333
> Stack trace:
> #0 Zend/Db/Adapter/Abstract.php(832): Zend_Db_Adapter_Mysqli->_connect()
> #1 Zend/Db/Adapter/Abstract.php(902):
> Zend_Db_Adapter_Abstract->quote('376', NULL)
> #2 Zend/Db/Select.php(1000):
> Zend_Db_Adapter_Abstract->quoteInto('table...', '376', NULL)
> #3 Zend/Db/Select.php(475): Zend_Db_Select->_where('table...', '376', NULL,
> true)
> ...
>
> I am on shared FreeBSD hosting.
>
> Is it possible that there is some connection overhead that code like this
> can generate?
>
> Regards,
> Saša Stamenković
>
umpirsky
2010-05-19 09:42:57 UTC
Permalink
Anyone who knows how this works in the backround?

It really kills the server. This error spam the error log, and site goes
down, but I still can to connect to db from mysql client (other IP).
--
View this message in context: http://zend-framework-community.634137.n4.nabble.com/Saving-many-Zend-Db-Table-Rows-in-for-loop-tp2220281p2222551.html
Sent from the Zend Framework mailing list archive at Nabble.com.
Jurian Sluiman
2010-05-19 09:48:27 UTC
Permalink
You executes many queries in a for loop, absolutely not recommended. Use
transactions or even better, loop through all models and create one query:
UPDATE my_table SET status='ACTIVE' where id IN (1,2,3,4,5,6,7,8). Both are
possible with ZF.

Regards, Jurian

PS. Why activate a record by setting a value to string "ACTIVE"? You should
look at some performance guide and use a kind of boolean field to set the
state.
--
Jurian Sluiman
CTO Soflomo V.O.F.
http://soflomo.com

On Wednesday 19 May 2010 11:42:57 umpirsky wrote:
> Anyone who knows how this works in the backround?
>
> It really kills the server. This error spam the error log, and site goes
> down, but I still can to connect to db from mysql client (other IP).
Саша Стаменковић
2010-05-19 10:12:16 UTC
Permalink
So, if I put

$table->getAdapter()->beginTransaction();

before, and

$table->getAdapter()->commit();

after for loop, it should help? I'm not sure about this, but I can try.

Setting active is ok, this is enum, but you're right, I should go with one
update query, doing it on Zend_Db_Table_Row level is stupid, don't know why
I solved it this way at all.

Thanks.

Regards,
Saša Stamenković


On Wed, May 19, 2010 at 11:48 AM, Jurian Sluiman <***@juriansluiman.nl
> wrote:

> You executes many queries in a for loop, absolutely not recommended. Use
> transactions or even better, loop through all models and create one query:
> UPDATE my_table SET status='ACTIVE' where id IN (1,2,3,4,5,6,7,8). Both are
> possible with ZF.
>
> Regards, Jurian
>
> PS. Why activate a record by setting a value to string "ACTIVE"? You should
> look at some performance guide and use a kind of boolean field to set the
> state.
> --
> Jurian Sluiman
> CTO Soflomo V.O.F.
> http://soflomo.com
>
> On Wednesday 19 May 2010 11:42:57 umpirsky wrote:
> > Anyone who knows how this works in the backround?
> >
> > It really kills the server. This error spam the error log, and site goes
> > down, but I still can to connect to db from mysql client (other IP).
>
Саша Стаменковић
2010-05-20 09:42:19 UTC
Permalink
I tried to fix this with this code in my class extending Zend_Db_Table

public function publish($ids) {
$this->update(
array('status' => self::ACTIVE),
$this->getAdapter()->quoteInto('id IN (?)', $ids, Zend_Db::INT_TYPE)
);
}

and

public function fetchByIds($ids) {
return $this->fetchAll(
$this->select()
->from($this->_name)
->where($this->getAdapter()->quoteInto($this->_name . '.id IN (?)', $ids,
Zend_Db::INT_TYPE))
->order('date DESC')
);
}

but I still get similar error:

2010-05-20T10:08:40+02:00 ERR (3): exception
'Zend_Db_Adapter_Mysqli_Exception' with message 'User *** already has more
than 'max_user_connections' active connections' in
Zend/Db/Adapter/Mysqli.php:333
Stack trace:
#0 Zend/Db/Adapter/Abstract.php(832): Zend_Db_Adapter_Mysqli->_connect()
#1 Zend/Db/Adapter/Abstract.php(902): Zend_Db_Adapter_Abstract->quote('582',
NULL)
#2 Zend/Db/Select.php(1000): Zend_Db_Adapter_Abstract->quoteInto('table...',
'582', NULL)
#3 Zend/Db/Select.php(475): Zend_Db_Select->_where('table...', '582', NULL,
true)
...

Regards,
Saša Stamenković


On Wed, May 19, 2010 at 12:12 PM, Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>wrote:

> So, if I put
>
> $table->getAdapter()->beginTransaction();
>
> before, and
>
> $table->getAdapter()->commit();
>
> after for loop, it should help? I'm not sure about this, but I can try.
>
> Setting active is ok, this is enum, but you're right, I should go with one
> update query, doing it on Zend_Db_Table_Row level is stupid, don't know why
> I solved it this way at all.
>
> Thanks.
>
> Regards,
> Saša Stamenković
>
>
>
> On Wed, May 19, 2010 at 11:48 AM, Jurian Sluiman <
> subscribe-6FERFELu10UeTgRETm/J+***@public.gmane.org> wrote:
>
>> You executes many queries in a for loop, absolutely not recommended. Use
>> transactions or even better, loop through all models and create one query:
>> UPDATE my_table SET status='ACTIVE' where id IN (1,2,3,4,5,6,7,8). Both
>> are
>> possible with ZF.
>>
>> Regards, Jurian
>>
>> PS. Why activate a record by setting a value to string "ACTIVE"? You
>> should
>> look at some performance guide and use a kind of boolean field to set the
>> state.
>> --
>> Jurian Sluiman
>> CTO Soflomo V.O.F.
>> http://soflomo.com
>>
>> On Wednesday 19 May 2010 11:42:57 umpirsky wrote:
>> > Anyone who knows how this works in the backround?
>> >
>> > It really kills the server. This error spam the error log, and site goes
>> > down, but I still can to connect to db from mysql client (other IP).
>>
>
>
Thomas D.
2010-05-20 10:00:26 UTC
Permalink
Hi,

> [...]
> but I still get similar error:
>
> 2010-05-20T10:08:40+02:00 ERR (3): exception 'Zend_Db_Adapter_Mysqli_Exception'
> with message 'User *** already has more than 'max_user_connections' active
> connections' in Zend/Db/Adapter/Mysqli.php:333
> Stack trace:
> #0 Zend/Db/Adapter/Abstract.php(832): Zend_Db_Adapter_Mysqli->_connect()
> #1 Zend/Db/Adapter/Abstract.php(902): Zend_Db_Adapter_Abstract->quote('582', NULL)
> #2 Zend/Db/Select.php(1000): Zend_Db_Adapter_Abstract->quoteInto('table...', '582', NULL)
> #3 Zend/Db/Select.php(475): Zend_Db_Select->_where('table...', '582', NULL, true)
> [...]

I don't think that this problem is related to Zend_Db and/or is caused by a loop.
Zend_Db will use the same adapter for every table. So the script should only have one connection.

=> The problem should have another source.


Are you running on a shared host? Have you control over your mysqld? Then check your connections using mtop/MySQL Administrator to see what's the other connections and where they came from.

At least you should check what's the webservers max. connections. If your webserver can handle 1000 connections, but your mysqld allows only 100, then there is a configuration mismatch.


--
Regards,
Thomas
Саша Стаменковић
2010-05-20 10:03:56 UTC
Permalink
I can have max 15 connections on this shared hosting.

Because the connection I use is not persistanrt, but use pooling instead,
every query counts as new connection (not sure)?
Also, I thought the problem will dissapear when I remove loop, and use
IN(ids) approach, but looks like quoteInto() loops something that kills
server for each ID in array.

Regards,
Saša Stamenković


On Thu, May 20, 2010 at 12:00 PM, Thomas D. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org> wrote:

> Hi,
>
> > [...]
> > but I still get similar error:
> >
> > 2010-05-20T10:08:40+02:00 ERR (3): exception
> 'Zend_Db_Adapter_Mysqli_Exception'
> > with message 'User *** already has more than 'max_user_connections'
> active
> > connections' in Zend/Db/Adapter/Mysqli.php:333
> > Stack trace:
> > #0 Zend/Db/Adapter/Abstract.php(832): Zend_Db_Adapter_Mysqli->_connect()
> > #1 Zend/Db/Adapter/Abstract.php(902):
> Zend_Db_Adapter_Abstract->quote('582', NULL)
> > #2 Zend/Db/Select.php(1000):
> Zend_Db_Adapter_Abstract->quoteInto('table...', '582', NULL)
> > #3 Zend/Db/Select.php(475): Zend_Db_Select->_where('table...', '582',
> NULL, true)
> > [...]
>
> I don't think that this problem is related to Zend_Db and/or is caused by a
> loop.
> Zend_Db will use the same adapter for every table. So the script should
> only have one connection.
>
> => The problem should have another source.
>
>
> Are you running on a shared host? Have you control over your mysqld? Then
> check your connections using mtop/MySQL Administrator to see what's the
> other connections and where they came from.
>
> At least you should check what's the webservers max. connections. If your
> webserver can handle 1000 connections, but your mysqld allows only 100, then
> there is a configuration mismatch.
>
>
> --
> Regards,
> Thomas
>
>
>
Aleksey Zapparov
2010-05-20 10:08:52 UTC
Permalink
Hello,

Can you check one thing? Looks little bit dummy, but I never worked with
MySQLi in fact, so just to reveal my unknowlesge ;)) open up file:

Zend/Db/Adapter/Mysqli.php

and replace string (at line 282):

if ($this->_connection) {

with:

if ($this->isConnected()) {


2010/5/20 Саша Стаменковић <umpirsky-***@public.gmane.org>:
>
> I can have max 15 connections on this shared hosting.
> Because the connection I use is not persistanrt, but use pooling instead,
> every query counts as new connection (not sure)?
> Also, I thought the problem will dissapear when I remove loop, and use
> IN(ids) approach, but looks like quoteInto() loops something that kills
> server for each ID in array.
> Regards,
> Saša Stamenković
>
>
> On Thu, May 20, 2010 at 12:00 PM, Thomas D. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org> wrote:
>>
>> Hi,
>>
>> > [...]
>> > but I still get similar error:
>> >
>> > 2010-05-20T10:08:40+02:00 ERR (3): exception
>> > 'Zend_Db_Adapter_Mysqli_Exception'
>> > with message 'User *** already has  more than 'max_user_connections'
>> > active
>> > connections' in Zend/Db/Adapter/Mysqli.php:333
>> > Stack trace:
>> > #0 Zend/Db/Adapter/Abstract.php(832): Zend_Db_Adapter_Mysqli->_connect()
>> > #1 Zend/Db/Adapter/Abstract.php(902):
>> > Zend_Db_Adapter_Abstract->quote('582', NULL)
>> > #2 Zend/Db/Select.php(1000):
>> > Zend_Db_Adapter_Abstract->quoteInto('table...', '582', NULL)
>> > #3 Zend/Db/Select.php(475): Zend_Db_Select->_where('table...', '582',
>> > NULL, true)
>> > [...]
>>
>> I don't think that this problem is related to Zend_Db and/or is caused by
>> a loop.
>> Zend_Db will use the same adapter for every table. So the script should
>> only have one connection.
>>
>> => The problem should have another source.
>>
>>
>> Are you running on a shared host? Have you control over your mysqld? Then
>> check your connections using mtop/MySQL Administrator to see what's the
>> other connections and where they came from.
>>
>> At least you should check what's the webservers max. connections. If your
>> webserver can handle 1000 connections, but your mysqld allows only 100, then
>> there is a configuration mismatch.
>>
>>
>> --
>> 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: zapparov-962d5TIgE1qHXe+***@public.gmane.org

*Origin: Happy Hacking!
Саша Стаменковић
2010-05-20 10:15:19 UTC
Permalink
Ugh...too scared to do that. I will try later, after some testing. Thanks!

Regards,
Saša Stamenković


On Thu, May 20, 2010 at 12:08 PM, Aleksey Zapparov <ixti-***@public.gmane.org>wrote:

> Hello,
>
> Can you check one thing? Looks little bit dummy, but I never worked with
> MySQLi in fact, so just to reveal my unknowlesge ;)) open up file:
>
> Zend/Db/Adapter/Mysqli.php
>
> and replace string (at line 282):
>
> if ($this->_connection) {
>
> with:
>
> if ($this->isConnected()) {
>
>
> 2010/5/20 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
> >
> > I can have max 15 connections on this shared hosting.
> > Because the connection I use is not persistanrt, but use pooling instead,
> > every query counts as new connection (not sure)?
> > Also, I thought the problem will dissapear when I remove loop, and use
> > IN(ids) approach, but looks like quoteInto() loops something that kills
> > server for each ID in array.
> > Regards,
> > Saša Stamenković
> >
> >
> > On Thu, May 20, 2010 at 12:00 PM, Thomas D. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org>
> wrote:
> >>
> >> Hi,
> >>
> >> > [...]
> >> > but I still get similar error:
> >> >
> >> > 2010-05-20T10:08:40+02:00 ERR (3): exception
> >> > 'Zend_Db_Adapter_Mysqli_Exception'
> >> > with message 'User *** already has more than 'max_user_connections'
> >> > active
> >> > connections' in Zend/Db/Adapter/Mysqli.php:333
> >> > Stack trace:
> >> > #0 Zend/Db/Adapter/Abstract.php(832):
> Zend_Db_Adapter_Mysqli->_connect()
> >> > #1 Zend/Db/Adapter/Abstract.php(902):
> >> > Zend_Db_Adapter_Abstract->quote('582', NULL)
> >> > #2 Zend/Db/Select.php(1000):
> >> > Zend_Db_Adapter_Abstract->quoteInto('table...', '582', NULL)
> >> > #3 Zend/Db/Select.php(475): Zend_Db_Select->_where('table...', '582',
> >> > NULL, true)
> >> > [...]
> >>
> >> I don't think that this problem is related to Zend_Db and/or is caused
> by
> >> a loop.
> >> Zend_Db will use the same adapter for every table. So the script should
> >> only have one connection.
> >>
> >> => The problem should have another source.
> >>
> >>
> >> Are you running on a shared host? Have you control over your mysqld?
> Then
> >> check your connections using mtop/MySQL Administrator to see what's the
> >> other connections and where they came from.
> >>
> >> At least you should check what's the webservers max. connections. If
> your
> >> webserver can handle 1000 connections, but your mysqld allows only 100,
> then
> >> there is a configuration mismatch.
> >>
> >>
> >> --
> >> 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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>
> *Origin: Happy Hacking!
>
Aleksey Zapparov
2010-05-20 10:25:57 UTC
Permalink
Hello,

Don't see nothing scary ;)) I just tried such solution (in sinthetic test) and
it showed that there's no difference at all - so my proposal was useless, at
least in my environment.


2010/5/20 Саша Стаменковић <umpirsky-***@public.gmane.org>:
> Ugh...too scared to do that. I will try later, after some testing. Thanks!
>
> Regards,
> Saša Stamenković
>
>
> On Thu, May 20, 2010 at 12:08 PM, Aleksey Zapparov <ixti-***@public.gmane.org>
> wrote:
>>
>> Hello,
>>
>> Can you check one thing? Looks little bit dummy, but I never worked with
>> MySQLi in fact, so just to reveal my unknowlesge ;)) open up file:
>>
>> Zend/Db/Adapter/Mysqli.php
>>
>> and replace string (at line 282):
>>
>> if ($this->_connection) {
>>
>> with:
>>
>> if ($this->isConnected()) {
>>
>>
>> 2010/5/20 Саша Стаменковић <umpirsky-***@public.gmane.org>:
>> >
>> > I can have max 15 connections on this shared hosting.
>> > Because the connection I use is not persistanrt, but use pooling
>> > instead,
>> > every query counts as new connection (not sure)?
>> > Also, I thought the problem will dissapear when I remove loop, and use
>> > IN(ids) approach, but looks like quoteInto() loops something that kills
>> > server for each ID in array.
>> > Regards,
>> > Saša Stamenković
>> >
>> >
>> > On Thu, May 20, 2010 at 12:00 PM, Thomas D. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org>
>> > wrote:
>> >>
>> >> Hi,
>> >>
>> >> > [...]
>> >> > but I still get similar error:
>> >> >
>> >> > 2010-05-20T10:08:40+02:00 ERR (3): exception
>> >> > 'Zend_Db_Adapter_Mysqli_Exception'
>> >> > with message 'User *** already has  more than 'max_user_connections'
>> >> > active
>> >> > connections' in Zend/Db/Adapter/Mysqli.php:333
>> >> > Stack trace:
>> >> > #0 Zend/Db/Adapter/Abstract.php(832):
>> >> > Zend_Db_Adapter_Mysqli->_connect()
>> >> > #1 Zend/Db/Adapter/Abstract.php(902):
>> >> > Zend_Db_Adapter_Abstract->quote('582', NULL)
>> >> > #2 Zend/Db/Select.php(1000):
>> >> > Zend_Db_Adapter_Abstract->quoteInto('table...', '582', NULL)
>> >> > #3 Zend/Db/Select.php(475): Zend_Db_Select->_where('table...', '582',
>> >> > NULL, true)
>> >> > [...]
>> >>
>> >> I don't think that this problem is related to Zend_Db and/or is caused
>> >> by
>> >> a loop.
>> >> Zend_Db will use the same adapter for every table. So the script should
>> >> only have one connection.
>> >>
>> >> => The problem should have another source.
>> >>
>> >>
>> >> Are you running on a shared host? Have you control over your mysqld?
>> >> Then
>> >> check your connections using mtop/MySQL Administrator to see what's the
>> >> other connections and where they came from.
>> >>
>> >> At least you should check what's the webservers max. connections. If
>> >> your
>> >> webserver can handle 1000 connections, but your mysqld allows only 100,
>> >> then
>> >> there is a configuration mismatch.
>> >>
>> >>
>> >> --
>> >> 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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>
>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org

*Origin: Happy Hacking!
Саша Стаменковић
2010-05-20 10:27:04 UTC
Permalink
Hehe, good to know, thanks again.

Regards,
Saša Stamenković


On Thu, May 20, 2010 at 12:25 PM, Aleksey Zapparov <ixti-***@public.gmane.org>wrote:

> Hello,
>
> Don't see nothing scary ;)) I just tried such solution (in sinthetic test)
> and
> it showed that there's no difference at all - so my proposal was useless,
> at
> least in my environment.
>
>
> 2010/5/20 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
> > Ugh...too scared to do that. I will try later, after some testing.
> Thanks!
> >
> > Regards,
> > Saša Stamenković
> >
> >
> > On Thu, May 20, 2010 at 12:08 PM, Aleksey Zapparov <ixti-***@public.gmane.org>
> > wrote:
> >>
> >> Hello,
> >>
> >> Can you check one thing? Looks little bit dummy, but I never worked with
> >> MySQLi in fact, so just to reveal my unknowlesge ;)) open up file:
> >>
> >> Zend/Db/Adapter/Mysqli.php
> >>
> >> and replace string (at line 282):
> >>
> >> if ($this->_connection) {
> >>
> >> with:
> >>
> >> if ($this->isConnected()) {
> >>
> >>
> >> 2010/5/20 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
> >> >
> >> > I can have max 15 connections on this shared hosting.
> >> > Because the connection I use is not persistanrt, but use pooling
> >> > instead,
> >> > every query counts as new connection (not sure)?
> >> > Also, I thought the problem will dissapear when I remove loop, and use
> >> > IN(ids) approach, but looks like quoteInto() loops something that
> kills
> >> > server for each ID in array.
> >> > Regards,
> >> > Saša Stamenković
> >> >
> >> >
> >> > On Thu, May 20, 2010 at 12:00 PM, Thomas D. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org>
> >> > wrote:
> >> >>
> >> >> Hi,
> >> >>
> >> >> > [...]
> >> >> > but I still get similar error:
> >> >> >
> >> >> > 2010-05-20T10:08:40+02:00 ERR (3): exception
> >> >> > 'Zend_Db_Adapter_Mysqli_Exception'
> >> >> > with message 'User *** already has more than
> 'max_user_connections'
> >> >> > active
> >> >> > connections' in Zend/Db/Adapter/Mysqli.php:333
> >> >> > Stack trace:
> >> >> > #0 Zend/Db/Adapter/Abstract.php(832):
> >> >> > Zend_Db_Adapter_Mysqli->_connect()
> >> >> > #1 Zend/Db/Adapter/Abstract.php(902):
> >> >> > Zend_Db_Adapter_Abstract->quote('582', NULL)
> >> >> > #2 Zend/Db/Select.php(1000):
> >> >> > Zend_Db_Adapter_Abstract->quoteInto('table...', '582', NULL)
> >> >> > #3 Zend/Db/Select.php(475): Zend_Db_Select->_where('table...',
> '582',
> >> >> > NULL, true)
> >> >> > [...]
> >> >>
> >> >> I don't think that this problem is related to Zend_Db and/or is
> caused
> >> >> by
> >> >> a loop.
> >> >> Zend_Db will use the same adapter for every table. So the script
> should
> >> >> only have one connection.
> >> >>
> >> >> => The problem should have another source.
> >> >>
> >> >>
> >> >> Are you running on a shared host? Have you control over your mysqld?
> >> >> Then
> >> >> check your connections using mtop/MySQL Administrator to see what's
> the
> >> >> other connections and where they came from.
> >> >>
> >> >> At least you should check what's the webservers max. connections. If
> >> >> your
> >> >> webserver can handle 1000 connections, but your mysqld allows only
> 100,
> >> >> then
> >> >> there is a configuration mismatch.
> >> >>
> >> >>
> >> >> --
> >> >> 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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >>
> >> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>
> *Origin: Happy Hacking!
>
Thomas D.
2010-05-20 10:33:08 UTC
Permalink
Hi,

Саша Стаменковић wrote:
> I can have max 15 connections on this shared hosting.
>
> Because the connection I use is not persistanrt, but use pooling instead,
> every query counts as new connection (not sure)?

No!

In your bootstrap, you set up an adapter

$db = Zend_Db::factory('Adapter', array(
// Options
);

and set this as you default adapter for every Zend_Db_Table instance with

Zend_Db_Table::setDefaultAdapter($db);

Maybe you are using Zend_Application, which will do this for you, but this is happening somewhere (or you are creating your Zend_Db_Table instance and set an adapter in the constructor, e.g. "$myTable = new MyZendTable(array('db' => $adapter));").

So every time you are working with your database in the request, it will use the same adapter and therefore you are using the same connection.


I guess the problem is, that 15 connections aren't enough. 15 connections would limit you application to 15 concurrent requests, if every request will use one connection (if you use more than one connection per request, e.g. you are also using legacy (=non ZF) code too, the number of concurrent requests might be lower).

So you don't have a problem with ZF...


--
Regards,
Thomas
Саша Стаменковић
2010-05-20 10:43:23 UTC
Permalink
Thanks for the answer.

I mostly agree with you.

I use Zend_Application and have only one adapter active, no legacy code,
which is visible in debug bar also (only one adapter listed). Also, I do not
set adapters in my models, everithing is done automaticly, only config file.

This error occurs only on one admin page in my project, when I try to
iterate over rowset, in each iteration change sth in the row and save it
(old version) or I use quoteInto() with array of ids in update query (new
version).

I would like to hear what do you think about switching adapter from MySQLi
to PDO and setting 'persistent' => true for db connection in my config file?
Will that solve the problem? I'm trying to see the difference between
persistant and non persistant connection, since Zend_Db use non persistant
by default.

Regards,
Saša Stamenković


On Thu, May 20, 2010 at 12:33 PM, Thomas D. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org> wrote:

> Hi,
>
> Саша СтаЌеМкПвОћ wrote:
> > I can have max 15 connections on this shared hosting.
> >
> > Because the connection I use is not persistanrt, but use pooling instead,
> > every query counts as new connection (not sure)?
>
> No!
>
> In your bootstrap, you set up an adapter
>
> $db = Zend_Db::factory('Adapter', array(
> // Options
> );
>
> and set this as you default adapter for every Zend_Db_Table instance with
>
> Zend_Db_Table::setDefaultAdapter($db);
>
> Maybe you are using Zend_Application, which will do this for you, but this
> is happening somewhere (or you are creating your Zend_Db_Table instance and
> set an adapter in the constructor, e.g. "$myTable = new
> MyZendTable(array('db' => $adapter));").
>
> So every time you are working with your database in the request, it will
> use the same adapter and therefore you are using the same connection.
>
>
> I guess the problem is, that 15 connections aren't enough. 15 connections
> would limit you application to 15 concurrent requests, if every request will
> use one connection (if you use more than one connection per request, e.g.
> you are also using legacy (=non ZF) code too, the number of concurrent
> requests might be lower).
>
> So you don't have a problem with ZF...
>
>
> --
> Regards,
> Thomas
>
>
>
Thomas D.
2010-05-20 11:25:54 UTC
Permalink
Hi,

Саша Стаменковић wrote:
> This error occurs only on one admin page in my project,
> when I try to iterate over rowset, in each iteration
> change sth in the row and save it (old version)
> or I use quoteInto() with array of ids in update query (new version).

Can you monitor the used mysqld? This should really tell you, when and where the connections came from.
At least you should be able to do this, when you run your project in your local development system with your own mysqld.


> I would like to hear what do you think about switching adapter
> from MySQLi to PDO and setting 'persistent' => true for db connection
> in my config file? Will that solve the problem?

I don't think that this will solve your problem.

First, when you are using Zend_Db, I would recommend to use one of the native DB connectors, because Zend_Db is already your DB abstraction layer so you don't need another one. Read <http://blog.ulf-wendel.de/?p=187> for more information.

Secondly, you should understand what persistent connections means:
When you establish a persistent connection, you tell your mysqld "Do not *really* close the connection, if I (the client) close it". So when your script comes back and tries to establish a new connection, the mysqld will search in the connection pool if there is already an existing free connection and pass it back. This will save you time, because the work which is needed to establish a vanilla connection isn't required.

A benchmark:
Using a persistent connection will allow you to establish ~47000 connections per second with PHP 5.3 (a real C program like libmysql will allow you to establish ~78000 connections) on a test system.
The same test without persistent connection: PHP is only able to create 1816 connections per second and the C program only 1783 connections.

(Source: <http://www.phphatesme.com/blog/mysql/persistente-verbindungen/>)

So using persistent connection might save you time (btw: mysqli supports persistent connection since PHP 5.3), but cannot solve your current problem.

This article from 2002 is still actual:
<http://dev.mysql.com/news-and-events/newsletter/2002-11/a0000000086.html>


--
Regards,
Thomas
Саша Стаменковић
2010-05-20 12:44:07 UTC
Permalink
I don't know how to monitor mysqld, maybe get connection from adapter
with getConnection() and then retreive it from there and log?

Regards,
Saša Stamenković


On Thu, May 20, 2010 at 1:25 PM, Thomas D. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org> wrote:

> Hi,
>
> Саша СтаЌеМкПвОћ wrote:
> > This error occurs only on one admin page in my project,
> > when I try to iterate over rowset, in each iteration
> > change sth in the row and save it (old version)
> > or I use quoteInto() with array of ids in update query (new version).
>
> Can you monitor the used mysqld? This should really tell you, when and
> where the connections came from.
> At least you should be able to do this, when you run your project in your
> local development system with your own mysqld.
>
>
> > I would like to hear what do you think about switching adapter
> > from MySQLi to PDO and setting 'persistent' => true for db connection
> > in my config file? Will that solve the problem?
>
> I don't think that this will solve your problem.
>
> First, when you are using Zend_Db, I would recommend to use one of the
> native DB connectors, because Zend_Db is already your DB abstraction layer
> so you don't need another one. Read <http://blog.ulf-wendel.de/?p=187> for
> more information.
>
> Secondly, you should understand what persistent connections means:
> When you establish a persistent connection, you tell your mysqld "Do not
> *really* close the connection, if I (the client) close it". So when your
> script comes back and tries to establish a new connection, the mysqld will
> search in the connection pool if there is already an existing free
> connection and pass it back. This will save you time, because the work which
> is needed to establish a vanilla connection isn't required.
>
> A benchmark:
> Using a persistent connection will allow you to establish ~47000
> connections per second with PHP 5.3 (a real C program like libmysql will
> allow you to establish ~78000 connections) on a test system.
> The same test without persistent connection: PHP is only able to create
> 1816 connections per second and the C program only 1783 connections.
>
> (Source: <http://www.phphatesme.com/blog/mysql/persistente-verbindungen/>)
>
> So using persistent connection might save you time (btw: mysqli supports
> persistent connection since PHP 5.3), but cannot solve your current problem.
>
> This article from 2002 is still actual:
> <http://dev.mysql.com/news-and-events/newsletter/2002-11/a0000000086.html>
>
>
> --
> Regards,
> Thomas
>
>
>
Aleksey Zapparov
2010-05-20 12:56:44 UTC
Permalink
Hello,

Can you post (or send my privately) your table classes related to this issue?


2010/5/20 Саша Стаменковић <umpirsky-***@public.gmane.org>:
> I don't know how to monitor mysqld, maybe get connection from adapter
> with getConnection() and then retreive it from there and log?
>
> Regards,
> Saša Stamenković
>
>
> On Thu, May 20, 2010 at 1:25 PM, Thomas D. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org> wrote:
>>
>> Hi,
>>
>> Саша Стаменковић wrote:
>> > This error occurs only on one admin page in my project,
>> > when I try to iterate over rowset, in each iteration
>> > change sth in the row and save it (old version)
>> > or I use quoteInto() with array of ids in update query (new version).
>>
>> Can you monitor the used mysqld? This should really tell you, when and
>> where the connections came from.
>> At least you should be able to do this, when you run your project in your
>> local development system with your own mysqld.
>>
>>
>> > I would like to hear what do you think about switching adapter
>> > from MySQLi to PDO and setting 'persistent' => true for db connection
>> > in my config file? Will that solve the problem?
>>
>> I don't think that this will solve your problem.
>>
>> First, when you are using Zend_Db, I would recommend to use one of the
>> native DB connectors, because Zend_Db is already your DB abstraction layer
>> so you don't need another one. Read <http://blog.ulf-wendel.de/?p=187> for
>> more information.
>>
>> Secondly, you should understand what persistent connections means:
>> When you establish a persistent connection, you tell your mysqld "Do not
>> *really* close the connection, if I (the client) close it". So when your
>> script comes back and tries to establish a new connection, the mysqld will
>> search in the connection pool if there is already an existing free
>> connection and pass it back. This will save you time, because the work which
>> is needed to establish a vanilla connection isn't required.
>>
>> A benchmark:
>> Using a persistent connection will allow you to establish ~47000
>> connections per second with PHP 5.3 (a real C program like libmysql will
>> allow you to establish ~78000 connections) on a test system.
>> The same test without persistent connection: PHP is only able to create
>> 1816 connections per second and the C program only 1783 connections.
>>
>> (Source: <http://www.phphatesme.com/blog/mysql/persistente-verbindungen/>)
>>
>> So using persistent connection might save you time (btw: mysqli supports
>> persistent connection since PHP 5.3), but cannot solve your current problem.
>>
>> This article from 2002 is still actual:
>> <http://dev.mysql.com/news-and-events/newsletter/2002-11/a0000000086.html>
>>
>>
>> --
>> 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: zapparov-962d5TIgE1qHXe+***@public.gmane.org

*Origin: Happy Hacking!
Thomas D.
2010-05-20 13:02:03 UTC
Permalink
Hi,

Саша Стаменковић wrote:
> I don't know how to monitor mysqld, maybe get connection
> from adapter with getConnection() and then retreive it from there and log?

No. Monitoring your mysqld has nothing to do with PHP.

If you are on Unix or FreeBSD, you would use a tool like "mtop".
If you are on Windows you can use the MySQL Administrator from mysql.org.


P.s.: When you are quoting, how do you do that?
$table = new MyZendTable();
$adapter = $table->getAdapter();

$quoted_string = $adapter->quote(...);

If you are using "getConnection()" you will create an additional connection/object and won't use the existing one.
Maybe this is your problem...


--
Regards,
Thomas
Саша Стаменковић
2010-05-20 13:07:32 UTC
Permalink
I'm on shared hosting, so I can't do that.

I'm quoting like this:

return $this->fetchAll(
$this->select()
->from($this->_name)
->where($this->getAdapter()->quoteInto($this->_name . '.id IN (?)', $ids,
Zend_Db::INT_TYPE))
->order('date DESC')
);

where $ids is array of table primary keys.

Regards,
Saša Stamenković


On Thu, May 20, 2010 at 3:02 PM, Thomas D. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org> wrote:

> Hi,
>
> Саша СтаЌеМкПвОћ wrote:
> > I don't know how to monitor mysqld, maybe get connection
> > from adapter with getConnection() and then retreive it from there and
> log?
>
> No. Monitoring your mysqld has nothing to do with PHP.
>
> If you are on Unix or FreeBSD, you would use a tool like "mtop".
> If you are on Windows you can use the MySQL Administrator from mysql.org.
>
>
> P.s.: When you are quoting, how do you do that?
> $table = new MyZendTable();
> $adapter = $table->getAdapter();
>
> $quoted_string = $adapter->quote(...);
>
> If you are using "getConnection()" you will create an additional
> connection/object and won't use the existing one.
> Maybe this is your problem...
>
>
> --
> Regards,
> Thomas
>
>
>
Daniel Latter
2010-05-20 13:13:38 UTC
Permalink
Ive heard about a problem with the zf debug bar where it creates extra
connections? are you using this?

On 20 May 2010 14:07, Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org> wrote:

> I'm on shared hosting, so I can't do that.
>
> I'm quoting like this:
>
> return $this->fetchAll(
> $this->select()
> ->from($this->_name)
> ->where($this->getAdapter()->quoteInto($this->_name . '.id IN (?)', $ids,
> Zend_Db::INT_TYPE))
> ->order('date DESC')
> );
>
> where $ids is array of table primary keys.
>
> Regards,
> Saša Stamenković
>
>
>
> On Thu, May 20, 2010 at 3:02 PM, Thomas D. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org>wrote:
>
>> Hi,
>>
>> Саша СтаЌеМкПвОћ wrote:
>> > I don't know how to monitor mysqld, maybe get connection
>> > from adapter with getConnection() and then retreive it from there and
>> log?
>>
>> No. Monitoring your mysqld has nothing to do with PHP.
>>
>> If you are on Unix or FreeBSD, you would use a tool like "mtop".
>> If you are on Windows you can use the MySQL Administrator from mysql.org.
>>
>>
>> P.s.: When you are quoting, how do you do that?
>> $table = new MyZendTable();
>> $adapter = $table->getAdapter();
>>
>> $quoted_string = $adapter->quote(...);
>>
>> If you are using "getConnection()" you will create an additional
>> connection/object and won't use the existing one.
>> Maybe this is your problem...
>>
>>
>> --
>> Regards,
>> Thomas
>>
>>
>>
>
Саша Стаменковић
2010-05-20 13:14:58 UTC
Permalink
Only in development environment :)

Thanks.

Regards,
Saša Stamenković


On Thu, May 20, 2010 at 3:13 PM, Daniel Latter <dan.latter-***@public.gmane.org> wrote:

>
> Ive heard about a problem with the zf debug bar where it creates extra
> connections? are you using this?
>
>
> On 20 May 2010 14:07, Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org> wrote:
>
>> I'm on shared hosting, so I can't do that.
>>
>> I'm quoting like this:
>>
>> return $this->fetchAll(
>> $this->select()
>> ->from($this->_name)
>> ->where($this->getAdapter()->quoteInto($this->_name . '.id IN (?)', $ids,
>> Zend_Db::INT_TYPE))
>> ->order('date DESC')
>> );
>>
>> where $ids is array of table primary keys.
>>
>> Regards,
>> Saša Stamenković
>>
>>
>>
>> On Thu, May 20, 2010 at 3:02 PM, Thomas D. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org>wrote:
>>
>>> Hi,
>>>
>>> Саша СтаЌеМкПвОћ wrote:
>>> > I don't know how to monitor mysqld, maybe get connection
>>> > from adapter with getConnection() and then retreive it from there and
>>> log?
>>>
>>> No. Monitoring your mysqld has nothing to do with PHP.
>>>
>>> If you are on Unix or FreeBSD, you would use a tool like "mtop".
>>> If you are on Windows you can use the MySQL Administrator from mysql.org
>>> .
>>>
>>>
>>> P.s.: When you are quoting, how do you do that?
>>> $table = new MyZendTable();
>>> $adapter = $table->getAdapter();
>>>
>>> $quoted_string = $adapter->quote(...);
>>>
>>> If you are using "getConnection()" you will create an additional
>>> connection/object and won't use the existing one.
>>> Maybe this is your problem...
>>>
>>>
>>> --
>>> Regards,
>>> Thomas
>>>
>>>
>>>
>>
>
Саша Стаменковић
2010-05-24 13:06:47 UTC
Permalink
Yeah, quoteInto connects to db for every quoted value, and that breaks my
limit of 15 queries at once, even I only run one select and one update
query, it quotes array of values. What should I do?

Regards,
Saša Stamenković


On Thu, May 20, 2010 at 3:14 PM, Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>wrote:

> Only in development environment :)
>
> Thanks.
>
> Regards,
> Saša Stamenković
>
>
>
> On Thu, May 20, 2010 at 3:13 PM, Daniel Latter <dan.latter-***@public.gmane.org>wrote:
>
>>
>> Ive heard about a problem with the zf debug bar where it creates extra
>> connections? are you using this?
>>
>>
>> On 20 May 2010 14:07, Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org> wrote:
>>
>>> I'm on shared hosting, so I can't do that.
>>>
>>> I'm quoting like this:
>>>
>>> return $this->fetchAll(
>>> $this->select()
>>> ->from($this->_name)
>>> ->where($this->getAdapter()->quoteInto($this->_name . '.id IN (?)', $ids,
>>> Zend_Db::INT_TYPE))
>>> ->order('date DESC')
>>> );
>>>
>>> where $ids is array of table primary keys.
>>>
>>> Regards,
>>> Saša Stamenković
>>>
>>>
>>>
>>> On Thu, May 20, 2010 at 3:02 PM, Thomas D. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org>wrote:
>>>
>>>> Hi,
>>>>
>>>> Саша СтаЌеМкПвОћ wrote:
>>>> > I don't know how to monitor mysqld, maybe get connection
>>>> > from adapter with getConnection() and then retreive it from there and
>>>> log?
>>>>
>>>> No. Monitoring your mysqld has nothing to do with PHP.
>>>>
>>>> If you are on Unix or FreeBSD, you would use a tool like "mtop".
>>>> If you are on Windows you can use the MySQL Administrator from
>>>> mysql.org.
>>>>
>>>>
>>>> P.s.: When you are quoting, how do you do that?
>>>> $table = new MyZendTable();
>>>> $adapter = $table->getAdapter();
>>>>
>>>> $quoted_string = $adapter->quote(...);
>>>>
>>>> If you are using "getConnection()" you will create an additional
>>>> connection/object and won't use the existing one.
>>>> Maybe this is your problem...
>>>>
>>>>
>>>> --
>>>> Regards,
>>>> Thomas
>>>>
>>>>
>>>>
>>>
>>
>
Daniel Latter
2010-05-24 13:30:27 UTC
Permalink
Does it work without quoteInto?

If it does, you could do escape/filter the values yourself and then use
Zend_Db_Expr to create expression? OR Just generate string for use in
where() method yourself.

On 24 May 2010 14:06, Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org> wrote:

> Yeah, quoteInto connects to db for every quoted value, and that breaks my
> limit of 15 queries at once, even I only run one select and one update
> query, it quotes array of values. What should I do?
>
> Regards,
> Saša Stamenković
>
>
>
> On Thu, May 20, 2010 at 3:14 PM, Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>wrote:
>
>> Only in development environment :)
>>
>> Thanks.
>>
>> Regards,
>> Saša Stamenković
>>
>>
>>
>> On Thu, May 20, 2010 at 3:13 PM, Daniel Latter <dan.latter-***@public.gmane.org>wrote:
>>
>>>
>>> Ive heard about a problem with the zf debug bar where it creates extra
>>> connections? are you using this?
>>>
>>>
>>> On 20 May 2010 14:07, Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org> wrote:
>>>
>>>> I'm on shared hosting, so I can't do that.
>>>>
>>>> I'm quoting like this:
>>>>
>>>> return $this->fetchAll(
>>>> $this->select()
>>>> ->from($this->_name)
>>>> ->where($this->getAdapter()->quoteInto($this->_name . '.id IN (?)',
>>>> $ids, Zend_Db::INT_TYPE))
>>>> ->order('date DESC')
>>>> );
>>>>
>>>> where $ids is array of table primary keys.
>>>>
>>>> Regards,
>>>> Saša Stamenković
>>>>
>>>>
>>>>
>>>> On Thu, May 20, 2010 at 3:02 PM, Thomas D. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org>wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> Саша СтаЌеМкПвОћ wrote:
>>>>> > I don't know how to monitor mysqld, maybe get connection
>>>>> > from adapter with getConnection() and then retreive it from there and
>>>>> log?
>>>>>
>>>>> No. Monitoring your mysqld has nothing to do with PHP.
>>>>>
>>>>> If you are on Unix or FreeBSD, you would use a tool like "mtop".
>>>>> If you are on Windows you can use the MySQL Administrator from
>>>>> mysql.org.
>>>>>
>>>>>
>>>>> P.s.: When you are quoting, how do you do that?
>>>>> $table = new MyZendTable();
>>>>> $adapter = $table->getAdapter();
>>>>>
>>>>> $quoted_string = $adapter->quote(...);
>>>>>
>>>>> If you are using "getConnection()" you will create an additional
>>>>> connection/object and won't use the existing one.
>>>>> Maybe this is your problem...
>>>>>
>>>>>
>>>>> --
>>>>> Regards,
>>>>> Thomas
>>>>>
>>>>>
>>>>>
>>>>
>>>
>>
>
Саша Стаменковић
2010-05-24 13:37:48 UTC
Permalink
Yes, that is the option, reinventing the wheel, but I'll try.

Regards,
Saša Stamenković


On Mon, May 24, 2010 at 3:30 PM, Daniel Latter <dan.latter-***@public.gmane.org> wrote:

> Does it work without quoteInto?
>
> If it does, you could do escape/filter the values yourself and then use
> Zend_Db_Expr to create expression? OR Just generate string for use in
> where() method yourself.
>
>
> On 24 May 2010 14:06, Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org> wrote:
>
>> Yeah, quoteInto connects to db for every quoted value, and that breaks my
>> limit of 15 queries at once, even I only run one select and one update
>> query, it quotes array of values. What should I do?
>>
>> Regards,
>> Saša Stamenković
>>
>>
>>
>> On Thu, May 20, 2010 at 3:14 PM, Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>wrote:
>>
>>> Only in development environment :)
>>>
>>> Thanks.
>>>
>>> Regards,
>>> Saša Stamenković
>>>
>>>
>>>
>>> On Thu, May 20, 2010 at 3:13 PM, Daniel Latter <dan.latter-***@public.gmane.org>wrote:
>>>
>>>>
>>>> Ive heard about a problem with the zf debug bar where it creates extra
>>>> connections? are you using this?
>>>>
>>>>
>>>> On 20 May 2010 14:07, Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org> wrote:
>>>>
>>>>> I'm on shared hosting, so I can't do that.
>>>>>
>>>>> I'm quoting like this:
>>>>>
>>>>> return $this->fetchAll(
>>>>> $this->select()
>>>>> ->from($this->_name)
>>>>> ->where($this->getAdapter()->quoteInto($this->_name . '.id IN (?)',
>>>>> $ids, Zend_Db::INT_TYPE))
>>>>> ->order('date DESC')
>>>>> );
>>>>>
>>>>> where $ids is array of table primary keys.
>>>>>
>>>>> Regards,
>>>>> Saša Stamenković
>>>>>
>>>>>
>>>>>
>>>>> On Thu, May 20, 2010 at 3:02 PM, Thomas D. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org>wrote:
>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> Саша СтаЌеМкПвОћ wrote:
>>>>>> > I don't know how to monitor mysqld, maybe get connection
>>>>>> > from adapter with getConnection() and then retreive it from there
>>>>>> and log?
>>>>>>
>>>>>> No. Monitoring your mysqld has nothing to do with PHP.
>>>>>>
>>>>>> If you are on Unix or FreeBSD, you would use a tool like "mtop".
>>>>>> If you are on Windows you can use the MySQL Administrator from
>>>>>> mysql.org.
>>>>>>
>>>>>>
>>>>>> P.s.: When you are quoting, how do you do that?
>>>>>> $table = new MyZendTable();
>>>>>> $adapter = $table->getAdapter();
>>>>>>
>>>>>> $quoted_string = $adapter->quote(...);
>>>>>>
>>>>>> If you are using "getConnection()" you will create an additional
>>>>>> connection/object and won't use the existing one.
>>>>>> Maybe this is your problem...
>>>>>>
>>>>>>
>>>>>> --
>>>>>> Regards,
>>>>>> Thomas
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>
Thomas D.
2010-05-24 14:03:30 UTC
Permalink
Hi,

Саша Стаменковић wrote:
> Yeah, quoteInto connects to db for every quoted value,
> and that breaks my limit of 15 queries at once,
> even I only run one select and one update query,
> it quotes array of values. What should I do?

I cannot believe this. If this would be true, this would be a big bug. Think about the impact on performance.
I am monitoring our mysqld while developing and I didn't see such a behavior. Only one connection is established per database and used across multiple Zend_Db_Table instances.

So there must be something wrong in your code. E.g. a logical error (wrong usage).

What I would do:
I would run this code locally in a debugger and watch the mysqld query log. Then you should know, where's the problem is located.


--
Regards,
Thomas
Саша Стаменковић
2010-05-24 14:11:04 UTC
Permalink
I'm pretty sure it's one connection too, but for quoting value, does
Zend_Db_Adapter contacts mysql server in order to get some info about how to
quote it?

Regards,
Saša Stamenković


On Mon, May 24, 2010 at 4:03 PM, Thomas D. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org> wrote:

> Hi,
>
> Саша СтаЌеМкПвОћ wrote:
> > Yeah, quoteInto connects to db for every quoted value,
> > and that breaks my limit of 15 queries at once,
> > even I only run one select and one update query,
> > it quotes array of values. What should I do?
>
> I cannot believe this. If this would be true, this would be a big bug.
> Think about the impact on performance.
> I am monitoring our mysqld while developing and I didn't see such a
> behavior. Only one connection is established per database and used across
> multiple Zend_Db_Table instances.
>
> So there must be something wrong in your code. E.g. a logical error (wrong
> usage).
>
> What I would do:
> I would run this code locally in a debugger and watch the mysqld query log.
> Then you should know, where's the problem is located.
>
>
> --
> Regards,
> Thomas
>
>
>
Саша Стаменковић
2010-05-24 14:14:39 UTC
Permalink
I'm asking because I see quote method in exception trace:


2010-05-20T10:08:40+02:00 ERR (3): exception
'Zend_Db_Adapter_Mysqli_Exception' with message 'User *** already has more
than 'max_user_connections' active connections' in
Zend/Db/Adapter/Mysqli.php:333
Stack trace:
#0 Zend/Db/Adapter/Abstract.php(832): Zend_Db_Adapter_Mysqli->_connect()
#1 Zend/Db/Adapter/Abstract.php(902): Zend_Db_Adapter_Abstract->quote('582',
NULL)
#2 Zend/Db/Select.php(1000): Zend_Db_Adapter_Abstract->quoteInto('table...',
'582', NULL)
#3 Zend/Db/Select.php(475): Zend_Db_Select->_where('table...', '582', NULL,
true)
...

Regards,
Saša Stamenković


On Mon, May 24, 2010 at 4:11 PM, Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>wrote:

> I'm pretty sure it's one connection too, but for quoting value, does
> Zend_Db_Adapter contacts mysql server in order to get some info about how to
> quote it?
>
> Regards,
> Saša Stamenković
>
>
>
> On Mon, May 24, 2010 at 4:03 PM, Thomas D. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org>wrote:
>
>> Hi,
>>
>> Саша СтаЌеМкПвОћ wrote:
>> > Yeah, quoteInto connects to db for every quoted value,
>> > and that breaks my limit of 15 queries at once,
>> > even I only run one select and one update query,
>> > it quotes array of values. What should I do?
>>
>> I cannot believe this. If this would be true, this would be a big bug.
>> Think about the impact on performance.
>> I am monitoring our mysqld while developing and I didn't see such a
>> behavior. Only one connection is established per database and used across
>> multiple Zend_Db_Table instances.
>>
>> So there must be something wrong in your code. E.g. a logical error (wrong
>> usage).
>>
>> What I would do:
>> I would run this code locally in a debugger and watch the mysqld query
>> log. Then you should know, where's the problem is located.
>>
>>
>> --
>> Regards,
>> Thomas
>>
>>
>>
>
Thomas D.
2010-05-24 15:19:18 UTC
Permalink
Hi,

Саша Стаменковић wrote:
>> [...]
>> So there must be something wrong in your code. E.g. a logical error (wrong usage).
>
> I'm pretty sure it's one connection too, but for quoting value,
> does Zend_Db_Adapter contacts mysql server in order to get some
> info about how to quote it?
>
> I'm asking because I see quote method in exception trace:
>
> 2010-05-20T10:08:40+02:00 ERR (3): exception 'Zend_Db_Adapter_Mysqli_Exception'
> with message 'User *** already has more than 'max_user_connections' active connections'
> in Zend/Db/Adapter/Mysqli.php:333
> Stack trace:
> #0 Zend/Db/Adapter/Abstract.php(832): Zend_Db_Adapter_Mysqli->_connect()
> #1 Zend/Db/Adapter/Abstract.php(902): Zend_Db_Adapter_Abstract->quote('582', NULL)
> #2 Zend/Db/Select.php(1000): Zend_Db_Adapter_Abstract->quoteInto('table...', '582', NULL)
> #3 Zend/Db/Select.php(475): Zend_Db_Select->_where('table...', '582', NULL, true)
> ...

When you create a new Zend_Db_Table instance, no DB connection is used.
So the following code won't establish any DB connections:

---
<?php
require_once 'Zend/Loader/Autoloader.php';
$autoloader = Zend_Loader_Autoloader::getInstance();

$db = Zend_Db::factory('Pdo_Mysql', array(
'host' => 'localhost',
'username' => 'user',
'password' => 'password',
'dbname' => 'dbname'
));

Zend_Db_Table::setDefaultAdapter($db);

$table = new Zend_Db_Table('tableName');
---

In the moment you do something with $table, Zend_Db_Table will do the "setup" by calling "$this->_setupPrimaryKey()".

Keep in mind, that the used quoteInto() methods comes from the adapter. There is no $table->quoteInto() method. You will do something like

---
$value = '2010-05-24';
$adapter = $table->getAdapter();
$quotedValue = $adapter->quoteInto('WHERE date < ?', $value);
---

The quoteInto() method will use the quote() method internally, which will call _connect() method.
But this method will only establish a connection, if this adapter hasn't yet established one:

>From Zend\Db\Adapter\Mysqli.php:
protected function _connect()
{
if ($this->_connection) {
return;
}
// [...]

So again, Zend_Db_* itself cannot be the problem. This component will reuse one connection across all instances where it's possible.

The stack trace you see will just tell you, that I wasn't able to make a connection. Now, after I showed to you, that when you use a table/adapter, it will establish a connection, if the used adapter hasn't yet establish one, it shouldn't be surprising, that a quoteInto() call was the start point. You understand?

The problem might be (if there aren't too many parallel requests to your application as I wrote some days ago), that you are using Zend_Db_* the wrong way. E.g. forcing new connection etc. - nobody can tell you in detail, without knowing your code, what the problem in your case is ;-)

How you could find the problem should be easy: Run your code locally in a debugger and keep an eye on the mysqld query log. If you see more than one

Time Id Command Argument
100524 17:15:11 1 Connect ***@localhost on tableName

you know there is something wrong in your code. Then running your request step by step in a debugger will tell you exactly, which code is causing the problem.


--
Regards,
Thomas
Bill Karwin
2010-05-24 16:29:00 UTC
Permalink
Each instance of Zend_Db_Adapter should never create more than one
connection.

The _connect() method is a no-op if you are already connected. It
does not create a new connection each time you use quoteInto().

Calling getConnection() also returns the existing connection. It
creates a new connection only if you weren't connected yet. This is
part of the lazy-connection logic.

Regards,
Bill Karwin

On May 24, 2010, at 7:14 AM, Саша СтаЌеМкПвОћ wrote:

> I'm asking because I see quote method in exception trace:
>
>
> 2010-05-20T10:08:40+02:00 ERR (3): exception
> 'Zend_Db_Adapter_Mysqli_Exception' with message 'User *** already
> has more than 'max_user_connections' active connections' in Zend/Db/
> Adapter/Mysqli.php:333
> Stack trace:
> #0 Zend/Db/Adapter/Abstract.php(832): Zend_Db_Adapter_Mysqli-
> >_connect()
> #1 Zend/Db/Adapter/Abstract.php(902): Zend_Db_Adapter_Abstract-
> >quote('582', NULL)
> #2 Zend/Db/Select.php(1000): Zend_Db_Adapter_Abstract-
> >quoteInto('table...', '582', NULL)
> #3 Zend/Db/Select.php(475): Zend_Db_Select->_where('table...',
> '582', NULL, true)
> ...
>
> Regards,
> Saša Stamenković
>
Hector Virgen
2010-05-24 17:25:05 UTC
Permalink
If you call the factory method twice with the same parameters, will that
create two connections? Саша, is it possible that somewhere in your code you
are calling the factory method more than once to connect to your DB?
Specifically Zend_Db::factory().

--
Hector


On Mon, May 24, 2010 at 9:29 AM, Bill Karwin <bill-baf+sBa3IK/QT0dZR+***@public.gmane.org> wrote:

> Each instance of Zend_Db_Adapter should never create more than one
> connection.
>
> The _connect() method is a no-op if you are already connected. It does not
> create a new connection each time you use quoteInto().
>
> Calling getConnection() also returns the existing connection. It creates a
> new connection only if you weren't connected yet. This is part of the
> lazy-connection logic.
>
> Regards,
> Bill Karwin
>
> On May 24, 2010, at 7:14 AM, Саша СтаЌеМкПвОћ wrote:
>
> I'm asking because I see quote method in exception trace:
>
>
> 2010-05-20T10:08:40+02:00 ERR (3): exception
> 'Zend_Db_Adapter_Mysqli_Exception' with message 'User *** already has more
> than 'max_user_connections' active connections' in
> Zend/Db/Adapter/Mysqli.php:333
> Stack trace:
> #0 Zend/Db/Adapter/Abstract.php(832): Zend_Db_Adapter_Mysqli->_connect()
> #1 Zend/Db/Adapter/Abstract.php(902):
> Zend_Db_Adapter_Abstract->quote('582', NULL)
> #2 Zend/Db/Select.php(1000):
> Zend_Db_Adapter_Abstract->quoteInto('table...', '582', NULL)
> #3 Zend/Db/Select.php(475): Zend_Db_Select->_where('table...', '582', NULL,
> true)
> ...
>
> Regards,
> Saša Stamenković
>
>
>
Саша Стаменковић
2010-05-24 18:18:56 UTC
Permalink
No, I'm not calling it twice, its handled by Zend_Application, as
recommanded by Zend, and showed in quick start.

I'm not telling that there are more then one connections, but that quoteInto
communicates with mysql server in some way (executing some info query for
e.g.), otherwise, it should not fail in quote method.

Regards,
Saša Stamenković


On Mon, May 24, 2010 at 7:25 PM, Hector Virgen <djvirgen-***@public.gmane.org> wrote:

> If you call the factory method twice with the same parameters, will that
> create two connections? Саша, is it possible that somewhere in your code you
> are calling the factory method more than once to connect to your DB?
> Specifically Zend_Db::factory().
>
> --
> Hector
>
>
>
> On Mon, May 24, 2010 at 9:29 AM, Bill Karwin <bill-baf+sBa3IK/QT0dZR+***@public.gmane.org> wrote:
>
>> Each instance of Zend_Db_Adapter should never create more than one
>> connection.
>>
>> The _connect() method is a no-op if you are already connected. It does
>> not create a new connection each time you use quoteInto().
>>
>> Calling getConnection() also returns the existing connection. It creates
>> a new connection only if you weren't connected yet. This is part of the
>> lazy-connection logic.
>>
>> Regards,
>> Bill Karwin
>>
>> On May 24, 2010, at 7:14 AM, Саша СтаЌеМкПвОћ wrote:
>>
>> I'm asking because I see quote method in exception trace:
>>
>>
>> 2010-05-20T10:08:40+02:00 ERR (3): exception
>> 'Zend_Db_Adapter_Mysqli_Exception' with message 'User *** already has more
>> than 'max_user_connections' active connections' in
>> Zend/Db/Adapter/Mysqli.php:333
>> Stack trace:
>> #0 Zend/Db/Adapter/Abstract.php(832): Zend_Db_Adapter_Mysqli->_connect()
>> #1 Zend/Db/Adapter/Abstract.php(902):
>> Zend_Db_Adapter_Abstract->quote('582', NULL)
>> #2 Zend/Db/Select.php(1000):
>> Zend_Db_Adapter_Abstract->quoteInto('table...', '582', NULL)
>> #3 Zend/Db/Select.php(475): Zend_Db_Select->_where('table...', '582',
>> NULL, true)
>> ...
>>
>> Regards,
>> Saša Stamenković
>>
>>
>>
>
Hector Virgen
2010-05-24 18:32:33 UTC
Permalink
I think that's fine, quoteInto() should re-use the existing connection if it
needs to communicate with the db server.

--
Hector


On Mon, May 24, 2010 at 11:18 AM, Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>wrote:

> No, I'm not calling it twice, its handled by Zend_Application, as
> recommanded by Zend, and showed in quick start.
>
> I'm not telling that there are more then one connections, but that
> quoteInto communicates with mysql server in some way (executing some info
> query for e.g.), otherwise, it should not fail in quote method.
>
> Regards,
> Saša Stamenković
>
>
>
> On Mon, May 24, 2010 at 7:25 PM, Hector Virgen <djvirgen-***@public.gmane.org> wrote:
>
>> If you call the factory method twice with the same parameters, will that
>> create two connections? Саша, is it possible that somewhere in your code you
>> are calling the factory method more than once to connect to your DB?
>> Specifically Zend_Db::factory().
>>
>> --
>> Hector
>>
>>
>>
>> On Mon, May 24, 2010 at 9:29 AM, Bill Karwin <bill-baf+sBa3IK/QT0dZR+***@public.gmane.org> wrote:
>>
>>> Each instance of Zend_Db_Adapter should never create more than one
>>> connection.
>>>
>>> The _connect() method is a no-op if you are already connected. It does
>>> not create a new connection each time you use quoteInto().
>>>
>>> Calling getConnection() also returns the existing connection. It creates
>>> a new connection only if you weren't connected yet. This is part of the
>>> lazy-connection logic.
>>>
>>> Regards,
>>> Bill Karwin
>>>
>>> On May 24, 2010, at 7:14 AM, Саша СтаЌеМкПвОћ wrote:
>>>
>>> I'm asking because I see quote method in exception trace:
>>>
>>>
>>> 2010-05-20T10:08:40+02:00 ERR (3): exception
>>> 'Zend_Db_Adapter_Mysqli_Exception' with message 'User *** already has more
>>> than 'max_user_connections' active connections' in
>>> Zend/Db/Adapter/Mysqli.php:333
>>> Stack trace:
>>> #0 Zend/Db/Adapter/Abstract.php(832): Zend_Db_Adapter_Mysqli->_connect()
>>> #1 Zend/Db/Adapter/Abstract.php(902):
>>> Zend_Db_Adapter_Abstract->quote('582', NULL)
>>> #2 Zend/Db/Select.php(1000):
>>> Zend_Db_Adapter_Abstract->quoteInto('table...', '582', NULL)
>>> #3 Zend/Db/Select.php(475): Zend_Db_Select->_where('table...', '582',
>>> NULL, true)
>>> ...
>>>
>>> Regards,
>>> Saša Stamenković
>>>
>>>
>>>
>>
>
Саша Стаменковић
2010-05-24 18:37:39 UTC
Permalink
Does it need to communicate with the db server?

Regards,
Saša Stamenković


On Mon, May 24, 2010 at 8:32 PM, Hector Virgen <djvirgen-***@public.gmane.org> wrote:

> I think that's fine, quoteInto() should re-use the existing connection if
> it needs to communicate with the db server.
>
> --
> Hector
>
>
>
> On Mon, May 24, 2010 at 11:18 AM, Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>wrote:
>
>> No, I'm not calling it twice, its handled by Zend_Application, as
>> recommanded by Zend, and showed in quick start.
>>
>> I'm not telling that there are more then one connections, but that
>> quoteInto communicates with mysql server in some way (executing some info
>> query for e.g.), otherwise, it should not fail in quote method.
>>
>> Regards,
>> Saša Stamenković
>>
>>
>>
>> On Mon, May 24, 2010 at 7:25 PM, Hector Virgen <djvirgen-***@public.gmane.org>wrote:
>>
>>> If you call the factory method twice with the same parameters, will that
>>> create two connections? Саша, is it possible that somewhere in your code you
>>> are calling the factory method more than once to connect to your DB?
>>> Specifically Zend_Db::factory().
>>>
>>> --
>>> Hector
>>>
>>>
>>>
>>> On Mon, May 24, 2010 at 9:29 AM, Bill Karwin <bill-baf+sBa3IK/QT0dZR+***@public.gmane.org> wrote:
>>>
>>>> Each instance of Zend_Db_Adapter should never create more than one
>>>> connection.
>>>>
>>>> The _connect() method is a no-op if you are already connected. It does
>>>> not create a new connection each time you use quoteInto().
>>>>
>>>> Calling getConnection() also returns the existing connection. It
>>>> creates a new connection only if you weren't connected yet. This is part of
>>>> the lazy-connection logic.
>>>>
>>>> Regards,
>>>> Bill Karwin
>>>>
>>>> On May 24, 2010, at 7:14 AM, Саша СтаЌеМкПвОћ wrote:
>>>>
>>>> I'm asking because I see quote method in exception trace:
>>>>
>>>>
>>>> 2010-05-20T10:08:40+02:00 ERR (3): exception
>>>> 'Zend_Db_Adapter_Mysqli_Exception' with message 'User *** already has more
>>>> than 'max_user_connections' active connections' in
>>>> Zend/Db/Adapter/Mysqli.php:333
>>>> Stack trace:
>>>> #0 Zend/Db/Adapter/Abstract.php(832): Zend_Db_Adapter_Mysqli->_connect()
>>>> #1 Zend/Db/Adapter/Abstract.php(902):
>>>> Zend_Db_Adapter_Abstract->quote('582', NULL)
>>>> #2 Zend/Db/Select.php(1000):
>>>> Zend_Db_Adapter_Abstract->quoteInto('table...', '582', NULL)
>>>> #3 Zend/Db/Select.php(475): Zend_Db_Select->_where('table...', '582',
>>>> NULL, true)
>>>> ...
>>>>
>>>> Regards,
>>>> Saša Stamenković
>>>>
>>>>
>>>>
>>>
>>
>
Thomas D.
2010-05-24 18:59:03 UTC
Permalink
Hi,

Саша Стаменковић wrote:
> Does it need to communicate with the db server?

Yes, it does.

And as I tried to show you in my mail ~3 hours ago, it's nothing bad, because quote() will reuse the existing connection.

I hope you understand, that quoteInto() is a method from the adapter and it's nothing else than a wrapper for the adapter's quote() method.

So when stack trace show you, that it failed to connect by calling quoteInto(), the used adapter hasn't yet established a connection. Start asking, why this adapter hasn't yet established a connection (if it isn't the first quoteInto() call, there was at least one quoteInto() call, which was successful. What's happen to the adapter used in this call?).


--
Regards,
Thomas
Саша Стаменковић
2010-05-24 19:03:03 UTC
Permalink
It might be that is the first quoteInto call, so connection should be
established.

Problem I see is, why it has to communicate with db server for each value in
array it quotes?!?!? Why not ask it for whatever it needs,a dn then use
given result for each value it quotes in array of values.

Regards,
Saša Stamenković


On Mon, May 24, 2010 at 8:59 PM, Thomas D. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org> wrote:

> Hi,
>
> Саша СтаЌеМкПвОћ wrote:
> > Does it need to communicate with the db server?
>
> Yes, it does.
>
> And as I tried to show you in my mail ~3 hours ago, it's nothing bad,
> because quote() will reuse the existing connection.
>
> I hope you understand, that quoteInto() is a method from the adapter and
> it's nothing else than a wrapper for the adapter's quote() method.
>
> So when stack trace show you, that it failed to connect by calling
> quoteInto(), the used adapter hasn't yet established a connection. Start
> asking, why this adapter hasn't yet established a connection (if it isn't
> the first quoteInto() call, there was at least one quoteInto() call, which
> was successful. What's happen to the adapter used in this call?).
>
>
> --
> Regards,
> Thomas
>
>
>
Thomas D.
2010-05-24 19:11:12 UTC
Permalink
Hi

Саша Стаменковић wrote:
> Problem I see is, why it has to communicate with db server
> for each value in array it quotes?!?!?
> Why not ask it for whatever it needs,a dn then use given result
> for each value it quotes in array of values.

You see a problem, where no problem is.

See the PHP documentation. Most adapter's escape functions requires an active link:
<http://www.php.net/manual/en/mysqli.real-escape-string.php>


--
Regards,
Thomas
Саша Стаменковић
2010-05-24 19:18:02 UTC
Permalink
Sure, when you have unlimited number of db operation over a period of time.
I'll come up with my own offline quoting.

Thanks everyone!

Regards,
Saša Stamenković


On Mon, May 24, 2010 at 9:11 PM, Thomas D. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org> wrote:

> Hi
>
> Саша СтаЌеМкПвОћ wrote:
> > Problem I see is, why it has to communicate with db server
> > for each value in array it quotes?!?!?
> > Why not ask it for whatever it needs,a dn then use given result
> > for each value it quotes in array of values.
>
> You see a problem, where no problem is.
>
> See the PHP documentation. Most adapter's escape functions requires an
> active link:
> <http://www.php.net/manual/en/mysqli.real-escape-string.php>
>
>
> --
> Regards,
> Thomas
>
>
>
Thomas D.
2010-05-24 19:27:15 UTC
Permalink
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
Саша Стаменковић
2010-05-24 19:34:01 UTC
Permalink
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. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org> 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
>
>
>
Aleksey Zapparov
2010-05-24 21:12:43 UTC
Permalink
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 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
> 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. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org> 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: zapparov-962d5TIgE1qHXe+***@public.gmane.org

*Origin: Happy Hacking!
Aleksey Zapparov
2010-05-24 21:44:47 UTC
Permalink
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 <ixti-***@public.gmane.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 Саша Стаменковић <umpirsky-***@public.gmane.org>:
>> 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. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org> 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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>
> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org

*Origin: Happy Hacking!
Thomas D.
2010-05-24 22:15:10 UTC
Permalink
Hi,

I can confirm, that Aleksey's application is working fine.

The index action:
100524 23:51:38 24 Connect ***@localhost on testdb
24 Query DESCRIBE `automobili_news`
24 Prepare [1] SELECT `automobili_news`.* FROM `automobili_news`
24 Execute [1] SELECT `automobili_news`.* FROM `automobili_news`
24 Quit

The update action:
100524 23:52:00 25 Connect ***@localhost on testdb
25 Prepare [1] UPDATE `automobili_news` SET `status` = ? WHERE (id IN (1, 2, ...))
25 Execute [1] UPDATE `automobili_news` SET `status` = 'INACTIVE' WHERE (id IN (1, 2, ...))
25 Quit

Just one connection, like everyone said in this discussion ;-)


But Саша is cycling through a result set, manipulating and saving row per row. Anyway, the fact that only one connection would be used stays the same. :)


--
Regards,
Thomas
Саша Стаменковић
2010-05-25 08:57:37 UTC
Permalink
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 <ixti-***@public.gmane.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 <ixti-***@public.gmane.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 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
> >> 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. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org>
> 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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >
> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>
> *Origin: Happy Hacking!
>
Саша Стаменковић
2010-05-25 09:35:53 UTC
Permalink
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, Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>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 <ixti-***@public.gmane.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 <ixti-***@public.gmane.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 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
>> >> 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. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org>
>> 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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>> >
>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>
>> *Origin: Happy Hacking!
>>
>
>
Aleksey Zapparov
2010-05-25 14:31:56 UTC
Permalink
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 Саша Стаменковић <umpirsky-***@public.gmane.org>:
> 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, Саша Стаменковић <umpirsky-***@public.gmane.org>
> wrote:
>>
>> Cache can be the temporary fix.
>>
>> Regards,
>> Saša Stamenković
>>
>>
>> On Tue, May 25, 2010 at 11:35 AM, Саша Стаменковић <umpirsky-***@public.gmane.org>
>> 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, Саша Стаменковић <umpirsky-***@public.gmane.org>
>>> 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 <ixti-***@public.gmane.orgg>
>>>> 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 <ixti-***@public.gmane.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 Саша Стаменковић <umpirsky-***@public.gmane.org>:
>>>>> >> 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. <whistl0r-gM/***@public.gmane.orgm>
>>>>> >> 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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>>>> >
>>>>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>>>>
>>>>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org

*Origin: Happy Hacking!
Aleksey Zapparov
2010-05-25 14:32:50 UTC
Permalink
Forgotten trace and profiler info.

2010/5/25 Aleksey Zapparov <ixti-***@public.gmane.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 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
>> 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, Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>
>> wrote:
>>>
>>> Cache can be the temporary fix.
>>>
>>> Regards,
>>> Saša Stamenković
>>>
>>>
>>> On Tue, May 25, 2010 at 11:35 AM, Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>
>>> 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, Саша СтаЌеМкПвОћ <***@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 <ixti-***@public.gmane.orgrg>
>>>>> 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 <ixti-***@public.gmane.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 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
>>>>>> >> 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. <***@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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>>>>> >
>>>>>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>>>>>
>>>>>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>
> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org

*Origin: Happy Hacking!
Aleksey Zapparov
2010-05-25 14:37:54 UTC
Permalink
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 <ixti-***@public.gmane.org>:
> Forgotten trace and profiler info.
>
> 2010/5/25 Aleksey Zapparov <ixti-***@public.gmane.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 Саша Стаменковић <umpirsky-***@public.gmane.org>:
>>> 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, Саша Стаменковић <umpirsky-***@public.gmane.org>
>>> wrote:
>>>>
>>>> Cache can be the temporary fix.
>>>>
>>>> Regards,
>>>> Saša Stamenković
>>>>
>>>>
>>>> On Tue, May 25, 2010 at 11:35 AM, Саша Стаменковић <***@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, Саша Стаменковић <***@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 <ixti-***@public.gmane.orgorg>
>>>>>> 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 <ixti-***@public.gmane.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 Саша Стаменковић <umpirsky-***@public.gmane.org>:
>>>>>>> >> 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. <***@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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>>>>>> >
>>>>>>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>>>>>>
>>>>>>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>
>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>
> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org

*Origin: Happy Hacking!
Саша Стаменковић
2010-05-25 17:57:48 UTC
Permalink
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 <ixti-***@public.gmane.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 <ixti-***@public.gmane.org>:
> > Forgotten trace and profiler info.
> >
> > 2010/5/25 Aleksey Zapparov <ixti-***@public.gmane.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 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
> >>> 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, Саша СтаЌеМкПвОћ <***@gmail.com
> >
> >>> wrote:
> >>>>
> >>>> Cache can be the temporary fix.
> >>>>
> >>>> Regards,
> >>>> Saša Stamenković
> >>>>
> >>>>
> >>>> On Tue, May 25, 2010 at 11:35 AM, Саша СтаЌеМкПвОћ <
> umpirsky-***@public.gmane.org>
> >>>> 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, Саша СтаЌеМкПвОћ <
> umpirsky-***@public.gmane.org>
> >>>>> 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 <
> ixti-***@public.gmane.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 <ixti-***@public.gmane.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 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
> >>>>>>> >> 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. <
> whistl0r-gM/Ye1E23mwN+***@public.gmane.org>
> >>>>>>> >> 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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >>>>>>> >
> >>>>>>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >>>>>>>
> >>>>>>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >>
> >> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >
> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>
> *Origin: Happy Hacking!
>
Bill Karwin
2010-05-25 18:21:40 UTC
Permalink
The default case is for unknown or unsupported fetch modes. This
throws an exception.

It's good to close the cursor before throwing an exception, because
it's likely that the statement will be aborted and without closing a
cursor, statement handles accumulate in the DB server and cause a
garbage collection problem.

Setting a valid fetch mode should not close the cursor, it only
changes the fetch mode for subsequent fetches. I.e. you can (in
theory) change the fetch mode several times as you fetch rows from the
same result set.

Regards,
Bill Karwin

On May 25, 2010, at 10:57 AM, Саша СтаЌеМкПвОћ wrote:

> Zend_Db_Statement in setFetchMode() calls $this->closeCursor(); only
> in default case for $mode, why not in other cases?!
Саша Стаменковић
2010-05-25 18:44:44 UTC
Permalink
Ah, yes, ok. I was afraid it does not close.

Regards,
Saša Stamenković


On Tue, May 25, 2010 at 8:21 PM, Bill Karwin <bill-baf+sBa3IK/QT0dZR+***@public.gmane.org> wrote:

> The default case is for unknown or unsupported fetch modes. This throws an
> exception.
>
> It's good to close the cursor before throwing an exception, because it's
> likely that the statement will be aborted and without closing a cursor,
> statement handles accumulate in the DB server and cause a garbage collection
> problem.
>
> Setting a valid fetch mode should not close the cursor, it only changes the
> fetch mode for subsequent fetches. I.e. you can (in theory) change the
> fetch mode several times as you fetch rows from the same result set.
>
> Regards,
> Bill Karwin
>
>
> On May 25, 2010, at 10:57 AM, Саша СтаЌеМкПвОћ wrote:
>
> Zend_Db_Statement in setFetchMode() calls $this->closeCursor(); only in
> default case for $mode, why not in other cases?!
>
>
>
Aleksey Zapparov
2010-05-25 19:40:36 UTC
Permalink
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 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
> 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 <ixti-***@public.gmane.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 <ixti-***@public.gmane.org>:
>> > Forgotten trace and profiler info.
>> >
>> > 2010/5/25 Aleksey Zapparov <ixti-***@public.gmane.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 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
>> >>> 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, Саша СтаЌеМкПвОћ
>> >>> <umpirsky-***@public.gmane.org>
>> >>> wrote:
>> >>>>
>> >>>> Cache can be the temporary fix.
>> >>>>
>> >>>> Regards,
>> >>>> Saša Stamenković
>> >>>>
>> >>>>
>> >>>> On Tue, May 25, 2010 at 11:35 AM, Саша СтаЌеМкПвОћ
>> >>>> <umpirsky-***@public.gmane.org>
>> >>>> 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, Саша СтаЌеМкПвОћ
>> >>>>> <umpirsky-***@public.gmane.org>
>> >>>>> 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
>> >>>>>> <ixti-***@public.gmane.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 <ixti-***@public.gmane.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 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
>> >>>>>>> >> 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.
>> >>>>>>> >> <whistl0r-gM/Ye1E23mwN+***@public.gmane.org>
>> >>>>>>> >> 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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>> >>>>>>> >
>> >>>>>>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>> >>>>>>>
>> >>>>>>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>> >>
>> >> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>> >
>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>
>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org

*Origin: Happy Hacking!
Aleksey Zapparov
2010-05-25 20:01:36 UTC
Permalink
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 <ixti-***@public.gmane.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 Саша Стаменковић <umpirsky-***@public.gmane.org>:
>> 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 <ixti-***@public.gmane.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 <ixti-***@public.gmane.org>:
>>> > Forgotten trace and profiler info.
>>> >
>>> > 2010/5/25 Aleksey Zapparov <ixti-***@public.gmane.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 Саша Стаменковић <umpirsky-***@public.gmane.org>:
>>> >>> 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, Саша Стаменковић
>>> >>> <umpirsky-***@public.gmane.org>
>>> >>> wrote:
>>> >>>>
>>> >>>> Cache can be the temporary fix.
>>> >>>>
>>> >>>> Regards,
>>> >>>> Saša Stamenković
>>> >>>>
>>> >>>>
>>> >>>> On Tue, May 25, 2010 at 11:35 AM, Саша Стаменковић
>>> >>>> <umpirsky-***@public.gmane.org>
>>> >>>> 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, Саша Стаменковић
>>> >>>>> <umpirsky-***@public.gmane.org>
>>> >>>>> 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
>>> >>>>>> <ixti-***@public.gmane.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 <ixti-***@public.gmane.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 Саша Стаменковић <umpirsky-***@public.gmane.org>:
>>> >>>>>>> >> 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.
>>> >>>>>>> >> <whistl0r-gM/Ye1E23mwN+***@public.gmane.org>
>>> >>>>>>> >> 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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>> >>>>>>> >
>>> >>>>>>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>> >>>>>>>
>>> >>>>>>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>> >>
>>> >> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>> >
>>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>>
>>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>
> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org

*Origin: Happy Hacking!
Саша Стаменковић
2010-05-25 20:24:43 UTC
Permalink
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 <ixti-***@public.gmane.org>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 <ixti-***@public.gmane.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 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
> >> 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 <ixti-***@public.gmane.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 <ixti-***@public.gmane.org>:
> >>> > Forgotten trace and profiler info.
> >>> >
> >>> > 2010/5/25 Aleksey Zapparov <ixti-***@public.gmane.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 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
> >>> >>> 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, Саша СтаЌеМкПвОћ
> >>> >>> <umpirsky-***@public.gmane.org>
> >>> >>> wrote:
> >>> >>>>
> >>> >>>> Cache can be the temporary fix.
> >>> >>>>
> >>> >>>> Regards,
> >>> >>>> Saša Stamenković
> >>> >>>>
> >>> >>>>
> >>> >>>> On Tue, May 25, 2010 at 11:35 AM, Саша СтаЌеМкПвОћ
> >>> >>>> <umpirsky-***@public.gmane.org>
> >>> >>>> 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, Саша СтаЌеМкПвОћ
> >>> >>>>> <umpirsky-***@public.gmane.org>
> >>> >>>>> 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
> >>> >>>>>> <ixti-***@public.gmane.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 <ixti-***@public.gmane.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 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
> >>> >>>>>>> >> 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.
> >>> >>>>>>> >> <whistl0r-gM/Ye1E23mwN+***@public.gmane.org>
> >>> >>>>>>> >> 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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >>> >>>>>>> >
> >>> >>>>>>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >>> >>>>>>>
> >>> >>>>>>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >>> >>
> >>> >> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >>> >
> >>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >>>
> >>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >
> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>
> *Origin: Happy Hacking!
>
Aleksey Zapparov
2010-05-25 20:32:02 UTC
Permalink
Hello everybody,

I have reported this as a MySQLi bug at: http://bugs.php.net/bug.php?id=51909
Please if somebody think (or know) that I was doing something wrong upon my
tests feel free to point it out - I'll try them with your proposed
solution and will
change my mind if I was wrong ;))


Пожалуйста, Саша! :)) *
* You are welcome, Саша! :))


2010/5/25 Саша Стаменковић <umpirsky-***@public.gmane.org>:
> 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 <ixti-***@public.gmane.org>
> 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 <ixti-***@public.gmane.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 Саша Стаменковић <umpirsky-***@public.gmane.org>:
>> >> 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 <ixti-***@public.gmane.orgg>
>> >> 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 <ixti-***@public.gmane.org>:
>> >>> > Forgotten trace and profiler info.
>> >>> >
>> >>> > 2010/5/25 Aleksey Zapparov <ixti-***@public.gmane.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 Саша Стаменковић <umpirsky-***@public.gmane.org>:
>> >>> >>> 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, Саша Стаменковић
>> >>> >>> <umpirsky-***@public.gmane.org>
>> >>> >>> wrote:
>> >>> >>>>
>> >>> >>>> Cache can be the temporary fix.
>> >>> >>>>
>> >>> >>>> Regards,
>> >>> >>>> Saša Stamenković
>> >>> >>>>
>> >>> >>>>
>> >>> >>>> On Tue, May 25, 2010 at 11:35 AM, Саша Стаменковић
>> >>> >>>> <umpirsky-***@public.gmane.org>
>> >>> >>>> 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, Саша Стаменковић
>> >>> >>>>> <umpirsky-***@public.gmane.org>
>> >>> >>>>> 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
>> >>> >>>>>> <ixti-***@public.gmane.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 <ixti-***@public.gmane.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 Саша Стаменковић <umpirsky-***@public.gmane.org>:
>> >>> >>>>>>> >> 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.
>> >>> >>>>>>> >> <whistl0r-gM/Ye1E23mwN+***@public.gmane.org>
>> >>> >>>>>>> >> 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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>> >>> >>>>>>> >
>> >>> >>>>>>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>> >>> >>>>>>>
>> >>> >>>>>>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>> >>> >>
>> >>> >> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>> >>> >
>> >>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>> >>>
>> >>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>> >
>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>
>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org

*Origin: Happy Hacking!
Aleksey Zapparov
2010-05-26 07:32:22 UTC
Permalink
Just to keep everybody informed. This bug was fixed at least in the latest
snapshot (php5.3-201005252030 | php5.3.3-dev). Now my proposal about
destructor is useless :)) as it works fine without it on the PHP snapshot
that I have tried :))


2010/5/25 Aleksey Zapparov <ixti-***@public.gmane.org>:
> Hello everybody,
>
> I have reported this as a MySQLi bug at: http://bugs.php.net/bug.php?id=51909
> Please if somebody think (or know) that I was doing something wrong upon my
> tests feel free to point it out - I'll try them with your proposed
> solution and will
> change my mind if I was wrong ;))
>
>
> Пожалуйста, Саша! :)) *
> * You are welcome, Саша! :))
>
>
> 2010/5/25 Саша Стаменковић <umpirsky-***@public.gmane.org>:
>> 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 <ixti-***@public.gmane.org>
>> 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 <ixti-***@public.gmane.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 Саша Стаменковић <umpirsky-***@public.gmane.org>:
>>> >> 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 <ixti-***@public.gmane.orgrg>
>>> >> 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 <ixti-***@public.gmane.org>:
>>> >>> > Forgotten trace and profiler info.
>>> >>> >
>>> >>> > 2010/5/25 Aleksey Zapparov <ixti-***@public.gmane.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 Саша Стаменковић <umpirsky-***@public.gmane.org>:
>>> >>> >>> 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, Саша Стаменковић
>>> >>> >>> <umpirsky-***@public.gmane.org>
>>> >>> >>> wrote:
>>> >>> >>>>
>>> >>> >>>> Cache can be the temporary fix.
>>> >>> >>>>
>>> >>> >>>> Regards,
>>> >>> >>>> Saša Stamenković
>>> >>> >>>>
>>> >>> >>>>
>>> >>> >>>> On Tue, May 25, 2010 at 11:35 AM, Саша Стаменковић
>>> >>> >>>> <umpirsky-***@public.gmane.org>
>>> >>> >>>> 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, Саша Стаменковић
>>> >>> >>>>> <umpirsky-***@public.gmane.org>
>>> >>> >>>>> 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
>>> >>> >>>>>> <ixti-***@public.gmane.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 <ixti-***@public.gmane.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 Саша Стаменковић <umpirsky-***@public.gmane.org>:
>>> >>> >>>>>>> >> 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.
>>> >>> >>>>>>> >> <whistl0r-gM/Ye1E23mwN+***@public.gmane.org>
>>> >>> >>>>>>> >> 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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>> >>> >>>>>>> >
>>> >>> >>>>>>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>> >>> >>>>>>>
>>> >>> >>>>>>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>> >>> >>
>>> >>> >> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>> >>> >
>>> >>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>> >>>
>>> >>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>> >
>>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>>
>>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>
> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org

*Origin: Happy Hacking!
Саша Стаменковић
2010-05-26 08:02:47 UTC
Permalink
Good to know, my hosting will soon upgrade to PHP 5.3.

Still, I'm not really informed about differences between mysqli and pdo.
When you work with Zend_Db, you can choose between this 2 with just one
config param.

I would like to know which one is faster?

Regards,
Saša Stamenković


On Wed, May 26, 2010 at 9:32 AM, Aleksey Zapparov <ixti-***@public.gmane.org>wrote:

> Just to keep everybody informed. This bug was fixed at least in the latest
> snapshot (php5.3-201005252030 | php5.3.3-dev). Now my proposal about
> destructor is useless :)) as it works fine without it on the PHP snapshot
> that I have tried :))
>
>
> 2010/5/25 Aleksey Zapparov <ixti-***@public.gmane.org>:
> > Hello everybody,
> >
> > I have reported this as a MySQLi bug at:
> http://bugs.php.net/bug.php?id=51909
> > Please if somebody think (or know) that I was doing something wrong upon
> my
> > tests feel free to point it out - I'll try them with your proposed
> > solution and will
> > change my mind if I was wrong ;))
> >
> >
> > ППжалуйста, Саша! :)) *
> > * You are welcome, Саша! :))
> >
> >
> > 2010/5/25 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
> >> 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 <ixti-***@public.gmane.orgg
> >
> >> 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 <ixti-***@public.gmane.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 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
> >>> >> 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 <
> ixti-***@public.gmane.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 <ixti-***@public.gmane.org>:
> >>> >>> > Forgotten trace and profiler info.
> >>> >>> >
> >>> >>> > 2010/5/25 Aleksey Zapparov <ixti-***@public.gmane.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 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
> >>> >>> >>> 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, Саша СтаЌеМкПвОћ
> >>> >>> >>> <umpirsky-***@public.gmane.org>
> >>> >>> >>> wrote:
> >>> >>> >>>>
> >>> >>> >>>> Cache can be the temporary fix.
> >>> >>> >>>>
> >>> >>> >>>> Regards,
> >>> >>> >>>> Saša Stamenković
> >>> >>> >>>>
> >>> >>> >>>>
> >>> >>> >>>> On Tue, May 25, 2010 at 11:35 AM, Саша СтаЌеМкПвОћ
> >>> >>> >>>> <umpirsky-***@public.gmane.org>
> >>> >>> >>>> 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, Саша СтаЌеМкПвОћ
> >>> >>> >>>>> <umpirsky-***@public.gmane.org>
> >>> >>> >>>>> 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
> >>> >>> >>>>>> <ixti-***@public.gmane.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 <ixti-***@public.gmane.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 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
> >>> >>> >>>>>>> >> 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.
> >>> >>> >>>>>>> >> <whistl0r-gM/Ye1E23mwN+***@public.gmane.org>
> >>> >>> >>>>>>> >> 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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >>> >>> >>>>>>> >
> >>> >>> >>>>>>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >>> >>> >>>>>>>
> >>> >>> >>>>>>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >>> >>> >>
> >>> >>> >> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >>> >>> >
> >>> >>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >>> >>>
> >>> >>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >>> >
> >>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >>>
> >>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >
> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>
> *Origin: Happy Hacking!
>
Aleksey Zapparov
2010-05-26 09:20:25 UTC
Permalink
Hello,

The bug will be fixed in 5.3.3 version. I was running 5.3.2 when I have
reproduced this error.

I don't know which one is really faster PDO or MySQLi but stormer.rb
that I was using to test was passing 1024 cycles four times faster with
PDO. But, of course, this should not be used as a point to decide. As
far as I can see MySQLi has some good things and PDO has it's own
good ones. But which ones - I don't know :)) Probably it's better to test
them for specific purpose (transactions, dummy selections, etc.)

Else I think it's the matter of preferences - something similar to linux
distros holy-wars, IMHO. So if you have more experience with MySQLi
then I think it's better to use it, as you'll be able to extend core features
with efficient code for your needs.

Anyway it would be interesting to see comparison of both (PDO MySQL
vs MySQLi) with tracking of memory/CPU usage and timings for different
tasks (selects, updates, transactioned operations, stored procedures etc).


2010/5/26 Саша Стаменковић <umpirsky-***@public.gmane.org>:
> Good to know, my hosting will soon upgrade to PHP 5.3.
> Still, I'm not really informed about differences between mysqli and pdo.
> When you work with Zend_Db, you can choose between this 2 with just one
> config param.
> I would like to know which one is faster?
> Regards,
> Saša Stamenković
>
>
> On Wed, May 26, 2010 at 9:32 AM, Aleksey Zapparov <ixti-***@public.gmane.org>
> wrote:
>>
>> Just to keep everybody informed. This bug was fixed at least in the latest
>> snapshot (php5.3-201005252030 | php5.3.3-dev). Now my proposal about
>> destructor is useless :)) as it works fine without it on the PHP snapshot
>> that I have tried :))
>>
>>
>> 2010/5/25 Aleksey Zapparov <ixti-***@public.gmane.org>:
>> > Hello everybody,
>> >
>> > I have reported this as a MySQLi bug at:
>> > http://bugs.php.net/bug.php?id=51909
>> > Please if somebody think (or know) that I was doing something wrong upon
>> > my
>> > tests feel free to point it out - I'll try them with your proposed
>> > solution and will
>> > change my mind if I was wrong ;))
>> >
>> >
>> > Пожалуйста, Саша! :)) *
>> > * You are welcome, Саша! :))
>> >
>> >
>> > 2010/5/25 Саша Стаменковић <umpirsky-***@public.gmane.org>:
>> >> 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
>> >> <ixti-***@public.gmane.org>
>> >> 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 <ixti-***@public.gmane.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 Саша Стаменковић <umpirsky-***@public.gmane.org>:
>> >>> >> 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
>> >>> >> <ixti-***@public.gmane.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 <ixti-***@public.gmane.org>:
>> >>> >>> > Forgotten trace and profiler info.
>> >>> >>> >
>> >>> >>> > 2010/5/25 Aleksey Zapparov <ixti-***@public.gmane.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 Саша Стаменковић <umpirsky-***@public.gmane.org>:
>> >>> >>> >>> 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, Саша Стаменковић
>> >>> >>> >>> <umpirsky-***@public.gmane.org>
>> >>> >>> >>> wrote:
>> >>> >>> >>>>
>> >>> >>> >>>> Cache can be the temporary fix.
>> >>> >>> >>>>
>> >>> >>> >>>> Regards,
>> >>> >>> >>>> Saša Stamenković
>> >>> >>> >>>>
>> >>> >>> >>>>
>> >>> >>> >>>> On Tue, May 25, 2010 at 11:35 AM, Саша Стаменковић
>> >>> >>> >>>> <umpirsky-***@public.gmane.org>
>> >>> >>> >>>> 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, Саша Стаменковић
>> >>> >>> >>>>> <umpirsky-***@public.gmane.org>
>> >>> >>> >>>>> 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
>> >>> >>> >>>>>> <ixti-***@public.gmane.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 <ixti-***@public.gmane.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 Саша Стаменковић <umpirsky-***@public.gmane.org>:
>> >>> >>> >>>>>>> >> 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.
>> >>> >>> >>>>>>> >> <whistl0r-gM/Ye1E23mwN+***@public.gmane.org>
>> >>> >>> >>>>>>> >> 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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>> >>> >>> >>>>>>> >
>> >>> >>> >>>>>>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>> >>> >>> >>>>>>>
>> >>> >>> >>>>>>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>> >>> >>> >>
>> >>> >>> >> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>> >>> >>> >
>> >>> >>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>> >>> >>>
>> >>> >>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>> >>> >
>> >>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>> >>>
>> >>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>> >
>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>>
>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org

*Origin: Happy Hacking!
Саша Стаменковић
2010-05-26 09:25:20 UTC
Permalink
Thanks. I think I saw some benchmark, but can't find it now. Still don't
know.

Regards,
Saša Stamenković


On Wed, May 26, 2010 at 11:20 AM, Aleksey Zapparov <ixti-***@public.gmane.org>wrote:

> Hello,
>
> The bug will be fixed in 5.3.3 version. I was running 5.3.2 when I have
> reproduced this error.
>
> I don't know which one is really faster PDO or MySQLi but stormer.rb
> that I was using to test was passing 1024 cycles four times faster with
> PDO. But, of course, this should not be used as a point to decide. As
> far as I can see MySQLi has some good things and PDO has it's own
> good ones. But which ones - I don't know :)) Probably it's better to test
> them for specific purpose (transactions, dummy selections, etc.)
>
> Else I think it's the matter of preferences - something similar to linux
> distros holy-wars, IMHO. So if you have more experience with MySQLi
> then I think it's better to use it, as you'll be able to extend core
> features
> with efficient code for your needs.
>
> Anyway it would be interesting to see comparison of both (PDO MySQL
> vs MySQLi) with tracking of memory/CPU usage and timings for different
> tasks (selects, updates, transactioned operations, stored procedures etc).
>
>
> 2010/5/26 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
> > Good to know, my hosting will soon upgrade to PHP 5.3.
> > Still, I'm not really informed about differences between mysqli and pdo.
> > When you work with Zend_Db, you can choose between this 2 with just one
> > config param.
> > I would like to know which one is faster?
> > Regards,
> > Saša Stamenković
> >
> >
> > On Wed, May 26, 2010 at 9:32 AM, Aleksey Zapparov <ixti-***@public.gmane.org>
> > wrote:
> >>
> >> Just to keep everybody informed. This bug was fixed at least in the
> latest
> >> snapshot (php5.3-201005252030 | php5.3.3-dev). Now my proposal about
> >> destructor is useless :)) as it works fine without it on the PHP
> snapshot
> >> that I have tried :))
> >>
> >>
> >> 2010/5/25 Aleksey Zapparov <ixti-***@public.gmane.org>:
> >> > Hello everybody,
> >> >
> >> > I have reported this as a MySQLi bug at:
> >> > http://bugs.php.net/bug.php?id=51909
> >> > Please if somebody think (or know) that I was doing something wrong
> upon
> >> > my
> >> > tests feel free to point it out - I'll try them with your proposed
> >> > solution and will
> >> > change my mind if I was wrong ;))
> >> >
> >> >
> >> > ППжалуйста, Саша! :)) *
> >> > * You are welcome, Саша! :))
> >> >
> >> >
> >> > 2010/5/25 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
> >> >> 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
> >> >> <ixti-***@public.gmane.org>
> >> >> 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 <ixti-***@public.gmane.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 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
> >> >>> >> 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
> >> >>> >> <ixti-***@public.gmane.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 <ixti-***@public.gmane.org>:
> >> >>> >>> > Forgotten trace and profiler info.
> >> >>> >>> >
> >> >>> >>> > 2010/5/25 Aleksey Zapparov <ixti-***@public.gmane.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 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
> >> >>> >>> >>> 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, Саша СтаЌеМкПвОћ
> >> >>> >>> >>> <umpirsky-***@public.gmane.org>
> >> >>> >>> >>> wrote:
> >> >>> >>> >>>>
> >> >>> >>> >>>> Cache can be the temporary fix.
> >> >>> >>> >>>>
> >> >>> >>> >>>> Regards,
> >> >>> >>> >>>> Saša Stamenković
> >> >>> >>> >>>>
> >> >>> >>> >>>>
> >> >>> >>> >>>> On Tue, May 25, 2010 at 11:35 AM, Саша СтаЌеМкПвОћ
> >> >>> >>> >>>> <umpirsky-***@public.gmane.org>
> >> >>> >>> >>>> 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, Саша СтаЌеМкПвОћ
> >> >>> >>> >>>>> <umpirsky-***@public.gmane.org>
> >> >>> >>> >>>>> 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
> >> >>> >>> >>>>>> <ixti-***@public.gmane.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 <ixti-***@public.gmane.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 Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>:
> >> >>> >>> >>>>>>> >> 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.
> >> >>> >>> >>>>>>> >> <whistl0r-gM/Ye1E23mwN+***@public.gmane.org>
> >> >>> >>> >>>>>>> >> 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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >> >>> >>> >>>>>>> >
> >> >>> >>> >>>>>>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >> >>> >>> >>>>>>>
> >> >>> >>> >>>>>>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >> >>> >>> >>
> >> >>> >>> >> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >> >>> >>> >
> >> >>> >>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >> >>> >>>
> >> >>> >>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >> >>> >
> >> >>> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >> >>>
> >> >>> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >> >
> >> > *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
> >>
> >> *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: zapparov-962d5TIgE1qHXe+***@public.gmane.org
>
> *Origin: Happy Hacking!
>
Thomas D.
2010-05-26 11:11:36 UTC
Permalink
Hi,

Саша Стаменковић wrote:
> Still, I'm not really informed about differences between mysqli
> and pdo. When you work with Zend_Db, you can choose between this
> 2 with just one config param.
>
> I would like to know which one is faster?

This question will be asked every month ;-)

You should first understand, what's the difference between these two (well, there are 3 "adapters", in PHP 5.3 there you can choose between 4 "adapters") are. To do that, have a look at the native PHP stack, how these adapters are implemented and what they do.

PDO for example is just another layer, which should "abstract" the database access (that's why PDO supports different DBEs and mysql* only MySql ;-)).

In general: Everything which is abstracting something will be slower than a native implementation of the same thing, because of the "overhead". But you should benefit from a great abstraction, so abstraction isn't bad at all ;-)

So when you are using Zend_Db_*, you are already using some kind of "abstraction", so you don't really need another abstraction, some PHP database API is offering to you.

In theory, PDO should be much slower than ext/mysql or mysqli is. For example PDO will prepare everything. But the nature of a PHP script is, that it will die after each request, so a prepared statement can only be used while the request, which prepared the statement, is active. So preparing a simple "SELECT * FROM articles WHERE isPublished = 1 ORDER BY date DESC" doesn't really makes sense, because this query will just be executed once in the request.

If you would prepare a select statement and execute it more than once with different parameters in one request, you would benefit from preparation (well, only when preparation is done on server-side, client-side prepared statements are another kind of abstraction and therefore aren't as good as server-side prepared statements).

So PDO is bad, isn't it? ;)

No! If you don't use any kind of abstraction like Zend_Db* is offering to you, the client-side prepared statements are offering you some kind of security. Binding parameters to a query makes them secure against known SQL injections.
At least other DBEs just need to implement the PDO interface to support PHP. They don't need to re-invent everything.

Ergo:
When you are using Zend_Db*, I would recommend to use ext/mysql or mysqli, because it's faster and you are already using a abstracted DBA.

If you don't use a abstracted DBA, I would recommend to use PDO.

In a normal application, you shouldn't notice any differences.

Only on high traffic applications you would notice differences. But in high traffic applications, you won't use Zend_Db*, because Zend_Db* won't support the DBE specific (optimized) commands, just "generalized" commands, which will work across all supported adapters. ;-)


P.s.: Ulf Wendel (from MySQL) wrote about that topic some month ago in this list: <http://zend-framework-community.634137.n4.nabble.com/PDO-or-Mysqli-td1556941.html>


--
Regards,
Thomas
Саша Стаменковић
2010-05-26 11:16:51 UTC
Permalink
That was great answer, thanks Thomas. As I expected, you can't be wrong
using one or another, and using mysqli is not a bad thing (if you are using
PHP 5.3+) :)

Regards,
Saša Stamenković


On Wed, May 26, 2010 at 1:11 PM, Thomas D. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org> wrote:

> Hi,
>
> Саша СтаЌеМкПвОћ wrote:
> > Still, I'm not really informed about differences between mysqli
> > and pdo. When you work with Zend_Db, you can choose between this
> > 2 with just one config param.
> >
> > I would like to know which one is faster?
>
> This question will be asked every month ;-)
>
> You should first understand, what's the difference between these two (well,
> there are 3 "adapters", in PHP 5.3 there you can choose between 4
> "adapters") are. To do that, have a look at the native PHP stack, how these
> adapters are implemented and what they do.
>
> PDO for example is just another layer, which should "abstract" the database
> access (that's why PDO supports different DBEs and mysql* only MySql ;-)).
>
> In general: Everything which is abstracting something will be slower than a
> native implementation of the same thing, because of the "overhead". But you
> should benefit from a great abstraction, so abstraction isn't bad at all ;-)
>
> So when you are using Zend_Db_*, you are already using some kind of
> "abstraction", so you don't really need another abstraction, some PHP
> database API is offering to you.
>
> In theory, PDO should be much slower than ext/mysql or mysqli is. For
> example PDO will prepare everything. But the nature of a PHP script is, that
> it will die after each request, so a prepared statement can only be used
> while the request, which prepared the statement, is active. So preparing a
> simple "SELECT * FROM articles WHERE isPublished = 1 ORDER BY date DESC"
> doesn't really makes sense, because this query will just be executed once in
> the request.
>
> If you would prepare a select statement and execute it more than once with
> different parameters in one request, you would benefit from preparation
> (well, only when preparation is done on server-side, client-side prepared
> statements are another kind of abstraction and therefore aren't as good as
> server-side prepared statements).
>
> So PDO is bad, isn't it? ;)
>
> No! If you don't use any kind of abstraction like Zend_Db* is offering to
> you, the client-side prepared statements are offering you some kind of
> security. Binding parameters to a query makes them secure against known SQL
> injections.
> At least other DBEs just need to implement the PDO interface to support
> PHP. They don't need to re-invent everything.
>
> Ergo:
> When you are using Zend_Db*, I would recommend to use ext/mysql or mysqli,
> because it's faster and you are already using a abstracted DBA.
>
> If you don't use a abstracted DBA, I would recommend to use PDO.
>
> In a normal application, you shouldn't notice any differences.
>
> Only on high traffic applications you would notice differences. But in high
> traffic applications, you won't use Zend_Db*, because Zend_Db* won't support
> the DBE specific (optimized) commands, just "generalized" commands, which
> will work across all supported adapters. ;-)
>
>
> P.s.: Ulf Wendel (from MySQL) wrote about that topic some month ago in this
> list: <
> http://zend-framework-community.634137.n4.nabble.com/PDO-or-Mysqli-td1556941.html
> >
>
>
> --
> Regards,
> Thomas
>
>
>
Bill Karwin
2010-05-26 18:18:41 UTC
Permalink
On May 26, 2010, at 4:11 AM, Thomas D. wrote:

> In theory, PDO should be much slower than ext/mysql or mysqli is.
> For example PDO will prepare everything.


I wrote the following on the February thread with Ulf Wendel that you
linked to, but I think it bears repeating:

MySQLPerformanceBlog.com did some benchmarks in an article about
"Prepared Statements" (http://www.mysqlperformanceblog.com/2006/08/02/mysql-prepared-statements/
).

Peter Zaitsev wrote:
> I’ve done a simple benchmark (using SysBench) to see performance of
> simple query (single row point select) using standard statement,
> prepared statement and have it served from query cache. Prepared
> statements give 2290 queries/sec which is significantly better than
> 2000 with standard statements but it is still well below 4470
> queries/sec when results are served from query cache.

Peter seems to say that the "overhead" of using prepared statements is
that they are 14.5% *faster* than using a non-prepared query
execution, at least in this simple test. I'd expect the relative
difference probably diminishes with a more complex query or a larger
result set.

In any case, we should be careful about citing round-trips as a
significant performance factor, because it discourages people from
using prepared queries when they should.

Regards,
Bill Karwin
Саша Стаменковић
2010-05-27 09:44:35 UTC
Permalink
Still sometimes get

PDOException with message 'SQLSTATE[42000] [1203] User *** already has
more than 'max_user_connections' active connections

:)


Regards,
Saša Stamenković


On Wed, May 26, 2010 at 8:18 PM, Bill Karwin <bill-baf+sBa3IK/QT0dZR+***@public.gmane.org> wrote:

>
> On May 26, 2010, at 4:11 AM, Thomas D. wrote:
>
> In theory, PDO should be much slower than ext/mysql or mysqli is. For
>> example PDO will prepare everything.
>>
>
>
> I wrote the following on the February thread with Ulf Wendel that you
> linked to, but I think it bears repeating:
>
> MySQLPerformanceBlog.com did some benchmarks in an article about "Prepared
> Statements" (
> http://www.mysqlperformanceblog.com/2006/08/02/mysql-prepared-statements/ ).
>
> Peter Zaitsev wrote:
> > I’ve done a simple benchmark (using SysBench) to see performance of
> > simple query (single row point select) using standard statement,
> > prepared statement and have it served from query cache. Prepared
> > statements give 2290 queries/sec which is significantly better than
> > 2000 with standard statements but it is still well below 4470
> > queries/sec when results are served from query cache.
>
> Peter seems to say that the "overhead" of using prepared statements is that
> they are 14.5% *faster* than using a non-prepared query execution, at least
> in this simple test. I'd expect the relative difference probably
> diminishes with a more complex query or a larger result set.
>
> In any case, we should be careful about citing round-trips as a significant
> performance factor, because it discourages people from using prepared
> queries when they should.
>
> Regards,
> Bill Karwin
Thomas D.
2010-05-27 18:09:56 UTC
Permalink
Hallo,

СЯшЯ СтЯменковић wrote:
> Still sometimes get
>
> PDOException with message 'SQLSTATE[42000] [1203] User *** already has
> more than 'max_user_connections' active connections

As I said in the beginning of this discussion (and btw, we can say that
this was the reason for your problem):

When you are allowed to have 15 connections to your database server, you
can serve 15 requests at the same time, when every request will establish 1
connection.

If you are establishing more than one connection per request, the number of
concurrent requests will be lower ;-)

Ask you hoster for more connections or switch to another one.

If this isn't possible, check if you can establish a connection in the
bootstrap and show a friendly error message to you users (e.g "Too much
load").

You could also limit the webserver, to just allow x concurrent requests, so
that the webserver will do the queue/error handling for you.


--
Grüße
Thomas
Bill Karwin
2010-05-27 18:25:16 UTC
Permalink
On May 27, 2010, at 11:09 AM, Thomas D. wrote:

> When you are allowed to have 15 connections to your database server,
> you
> can serve 15 requests at the same time, when every request will
> establish 1
> connection.

I completely agree with Thomas. If you are getting the error of too
many connections on your production website, it's most likely you have
>15 concurrent requests.

However, if you're getting the error on your development/test
environment, and you are certain that only one request is active,
that's a different matter.

Regards,
Bill Karwin
Thomas D.
2010-05-27 18:27:06 UTC
Permalink
Hi,

Bill Karwin wrote:
> I wrote the following on the February thread with Ulf Wendel that you
> linked to, but I think it bears repeating:
>
> [...]
>
> Peter seems to say that the "overhead" of using prepared statements is
> that they are 14.5% *faster* than using a non-prepared query
> execution, at least in this simple test. I'd expect the relative
> difference probably diminishes with a more complex query or a larger
> result set.

Peter was testing *real* prepared statements.
Real prepared statements are prepared on the DBE server-side.

Most people think, that when they are using PDO, which force them to use
prepared statements in most cases, that they are using *real* prepared
statements, but they aren't! PDO is just another abstraction PDO just
emulate prepared statements. That means, preparation is done client-side.
It's more a validation than preparation.
This has *nothing* to do with server-side prepared statements. Most of the
benefits a DBE is offering you when it is supporting prepared statements
cannot be used by client-side prepared statements.

That's why client-side prepared statements from a high performance
viewpoint are real show stopper. They do nothing than wasting time ;-)

For more:
<http://blog.ulf-wendel.de/?p=187#pdo>


> In any case, we should be careful about citing round-trips as a
> significant performance factor, because it discourages people from
> using prepared queries when they should.

*FULL ACK*

If anyone is not using some kind of abstraction like Zend_Db*, everyone
should prefer PDO. Not because it is faster (it isn't, but it isn't really
slower!), but because it is more secure by design, when you work with
prepared statements (because it is enforcing some kind of security).

But you should understand it. You should know why you are using PDO and why
you should prefer it. You shouldn't use something, just because someone has
told you "It's better" ;-)


--
Regards,
Thomas
Саша Стаменковић
2010-05-27 18:47:37 UTC
Permalink
Sure, I'll monitor this, dont happen too often. Thanks.

Regards,
Saša Stamenković


On Thu, May 27, 2010 at 8:27 PM, Thomas D. <whistl0r-gM/Ye1E23mwN+***@public.gmane.org> wrote:

> Hi,
>
> Bill Karwin wrote:
> > I wrote the following on the February thread with Ulf Wendel that you
> > linked to, but I think it bears repeating:
> >
> > [...]
> >
> > Peter seems to say that the "overhead" of using prepared statements is
> > that they are 14.5% *faster* than using a non-prepared query
> > execution, at least in this simple test. I'd expect the relative
> > difference probably diminishes with a more complex query or a larger
> > result set.
>
> Peter was testing *real* prepared statements.
> Real prepared statements are prepared on the DBE server-side.
>
> Most people think, that when they are using PDO, which force them to use
> prepared statements in most cases, that they are using *real* prepared
> statements, but they aren't! PDO is just another abstraction PDO just
> emulate prepared statements. That means, preparation is done client-side.
> It's more a validation than preparation.
> This has *nothing* to do with server-side prepared statements. Most of the
> benefits a DBE is offering you when it is supporting prepared statements
> cannot be used by client-side prepared statements.
>
> That's why client-side prepared statements from a high performance
> viewpoint are real show stopper. They do nothing than wasting time ;-)
>
> For more:
> <http://blog.ulf-wendel.de/?p=187#pdo>
>
>
> > In any case, we should be careful about citing round-trips as a
> > significant performance factor, because it discourages people from
> > using prepared queries when they should.
>
> *FULL ACK*
>
> If anyone is not using some kind of abstraction like Zend_Db*, everyone
> should prefer PDO. Not because it is faster (it isn't, but it isn't really
> slower!), but because it is more secure by design, when you work with
> prepared statements (because it is enforcing some kind of security).
>
> But you should understand it. You should know why you are using PDO and why
> you should prefer it. You shouldn't use something, just because someone has
> told you "It's better" ;-)
>
>
> --
> Regards,
> Thomas
>
>
Bill Karwin
2010-05-26 18:07:16 UTC
Permalink
On May 26, 2010, at 1:02 AM, Саша Стаменковић wrote:

> Still, I'm not really informed about differences between mysqli and
> pdo. When you work with Zend_Db, you can choose between this 2 with
> just one config param.
>
> I would like to know which one is faster?

I used to run the full set of Zend_Db unit tests many times a day,
with both PDO_MySQL and MySQLi enabled. There was no noticeable
difference in performance. So that's one anecdotal data point.

No doubt there are some cases that show a difference, and therefore
it's possible to construct a benchmark to magnify the difference. But
in ordinary, realistic usage, I don't think there's any significant
difference.

Certainly other factors (e.g. database indexes and using APC for
caching code and data) can overshadow any small difference between PDO
and MySQLi. Performance experts I listen to say that application
architecture matters far more than technical details like the choice
of API.

I would recommend against micro-optimizing, and especially premature
micro-optimizing.

Regards,
Bill Karwin
Bill Karwin
2010-05-24 22:40:51 UTC
Permalink
On May 24, 2010, at 12:18 PM, Саша Стаменковић wrote:

> Sure, when you have unlimited number of db operation over a period
> of time. I'll come up with my own offline quoting.

You should use the function provided by the database API. The
function mysqli_real_escape_string() requires an active database
connection because it needs to know the character set used by the
connection. But this isn't a problem; it's necessary so it can do
quoting safely.

Please DON'T try to write your own quoting function unless you are an
expert with multi-byte character sets. It's surprisingly difficult to
write a quoting function that's safe.

Read http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string

Regards,
Bill Karwin
Саша Стаменковић
2010-05-24 22:46:30 UTC
Permalink
Thanks Aleksey! It works perfect on my server. I don't get it, on the first
look, I do exactly same thing in my code. Will take a closer look at it
tommorow, and then share with you where the error was.

Only difference i see is that table is myisam, my was innodb. We'll see.

Regards,
Saša Stamenković


On Tue, May 25, 2010 at 12:40 AM, Bill Karwin <bill-baf+sBa3IK/QT0dZR+***@public.gmane.org> wrote:

> On May 24, 2010, at 12:18 PM, Саша СтаЌеМкПвОћ wrote:
>
> Sure, when you have unlimited number of db operation over a period of
>> time. I'll come up with my own offline quoting.
>>
>
> You should use the function provided by the database API. The function
> mysqli_real_escape_string() requires an active database connection because
> it needs to know the character set used by the connection. But this isn't a
> problem; it's necessary so it can do quoting safely.
>
> Please DON'T try to write your own quoting function unless you are an
> expert with multi-byte character sets. It's surprisingly difficult to write
> a quoting function that's safe.
>
> Read
> http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string
>
> Regards,
> Bill Karwin
Саша Стаменковић
2010-05-25 06:17:49 UTC
Permalink
I tested Alekseys app again on separate host with test table, and it worked
perfect. I switched store engine to innodb, worked with my model API methods

$this->view->assign('rows', $news->fetchNewsByIds(range(1,64)));
and
*$news->publishNews($ids);*
*
*
on 64 rows, and still no error.

I do similar in my project

$newsTable->publishNews($ids);
foreach ($newsTable->fetchNewsByIds($ids) as $news) {
$news->publishOnTwitter();
}

maybe I should move fetchNewsByIds out of the foreach, but that should not
be the problem.

To make it more clear, there are model methods:

/**
* Fetch news by Ids.
*
* @param array $ids array of news ids
* @return Automobili_Model_Table_Rowset_News
*/
public function fetchNewsByIds($ids) {
return $this->fetchAll(
$this->select()
->from($this->_name)
->where($this->getAdapter()->quoteInto('id IN (?)', $ids,
Zend_Db::INT_TYPE))
->order('date DESC')
);
}

/**
* Publish news.
*
* @param array $ids aray of news ids
*/
public function publishNews($ids) {
$this->update(
array('status' => self::ACTIVE),
$this->getAdapter()->quoteInto('id IN (?)', $ids, Zend_Db::INT_TYPE)
);
}

Row have this publish on twitter, which shouldn't have nothing to do with
the problem

public function publishOnTwitter() {
$credentials =
Zend_Controller_Front::getInstance()->getParam('bootstrap')->getOption('twitter');
$twitter = new Zend_Service_Twitter($credentials['username'],
$credentials['password']);
$twitter->status->update(sprintf('%s %s', $this->title, $this->url));
}

Does anyone see what I cannot see?

Regards,
Saša Stamenković


On Tue, May 25, 2010 at 12:46 AM, Саша СтаЌеМкПвОћ <umpirsky-***@public.gmane.org>wrote:

> Thanks Aleksey! It works perfect on my server. I don't get it, on the first
> look, I do exactly same thing in my code. Will take a closer look at it
> tommorow, and then share with you where the error was.
>
> Only difference i see is that table is myisam, my was innodb. We'll see.
>
> Regards,
> Saša Stamenković
>
>
>
> On Tue, May 25, 2010 at 12:40 AM, Bill Karwin <bill-baf+sBa3IK/QT0dZR+***@public.gmane.org> wrote:
>
>> On May 24, 2010, at 12:18 PM, Саша СтаЌеМкПвОћ wrote:
>>
>> Sure, when you have unlimited number of db operation over a period of
>>> time. I'll come up with my own offline quoting.
>>>
>>
>> You should use the function provided by the database API. The function
>> mysqli_real_escape_string() requires an active database connection because
>> it needs to know the character set used by the connection. But this isn't a
>> problem; it's necessary so it can do quoting safely.
>>
>> Please DON'T try to write your own quoting function unless you are an
>> expert with multi-byte character sets. It's surprisingly difficult to write
>> a quoting function that's safe.
>>
>> Read
>> http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string
>>
>> Regards,
>> Bill Karwin
>
>
>
Loading...