RejectedSoftware Forums

Sign up

Minimizing new DB connections

To avoid the cost of establishing a new connection to a MySQL DB
on potentially every page request, I tried making one connection to
the DB upon startup of my vibe.d app and then use that one connection
for each request. Worked fine until I tried making concurrent page
requests, at which point I (perhaps unsurprisingly) got a message about
the wrong fiber accessing a connection and then it died with an
InvalidMemoryOperationError. (But annoyingly, I can't seem to reproduce
it now.)

So I realize that's probably not a smart thing to do anyway, to share a
single connection across fibers. But how would I go about reusing DB
connections when possible? By using ConnectionPool, maybe? But I'm not
quite sure how to use that.

Re: Minimizing new DB connections

Am 10/24/2012 5:01 AM, schrieb Nick Sabalausky:

To avoid the cost of establishing a new connection to a MySQL DB
on potentially every page request, I tried making one connection to
the DB upon startup of my vibe.d app and then use that one connection
for each request. Worked fine until I tried making concurrent page
requests, at which point I (perhaps unsurprisingly) got a message about
the wrong fiber accessing a connection and then it died with an
InvalidMemoryOperationError. (But annoyingly, I can't seem to reproduce
it now.)

So I realize that's probably not a smart thing to do anyway, to share a
single connection across fibers. But how would I go about reusing DB
connections when possible? By using ConnectionPool, maybe? But I'm not
quite sure how to use that.

In my modified version of the mysql driver there is a trivial MysqlDB
class that uses a ConnectionPool. lockConnection() returns a RAII
struct that makes sure that a single connection is not used twice.

Usually I would also mirror the methods of the Connection class for
convenience, but since I don't really use it myself, I didn't put so
much time into it yet.

https://github.com/rejectedsoftware/mysql-native/blob/master/source/mysql/db.d

Re: Minimizing new DB connections

On Tue, 23 Oct 2012 23:01:06 -0400, Nick Sabalausky wrote:

To avoid the cost of establishing a new connection to a MySQL DB
on potentially every page request, I tried making one connection to
the DB upon startup of my vibe.d app and then use that one connection
for each request. Worked fine until I tried making concurrent page
requests, at which point I (perhaps unsurprisingly) got a message about
the wrong fiber accessing a connection and then it died with an
InvalidMemoryOperationError. (But annoyingly, I can't seem to reproduce
it now.)

So I realize that's probably not a smart thing to do anyway, to share a
single connection across fibers. But how would I go about reusing DB
connections when possible? By using ConnectionPool, maybe? But I'm not
quite sure how to use that.

At least at PostgreSQL driver libpq does not allow this behaviour and it is need organize queue.

In my application I am create one non shared connection in app.d static constructor, and just use it it thread. For two threads constructor creates two connections automatically (this assumption, I have not tested it)

Re: Minimizing new DB connections

On Wed, 24 Oct 2012 08:23:49 +0200
Sönke Ludwig sludwig@rejectedsoftware.com wrote:

Am 10/24/2012 5:01 AM, schrieb Nick Sabalausky:

To avoid the cost of establishing a new connection to a MySQL DB
on potentially every page request, I tried making one connection to
the DB upon startup of my vibe.d app and then use that one
connection for each request. Worked fine until I tried making
concurrent page requests, at which point I (perhaps unsurprisingly)
got a message about the wrong fiber accessing a connection and then
it died with an InvalidMemoryOperationError. (But annoyingly, I
can't seem to reproduce it now.)

So I realize that's probably not a smart thing to do anyway, to
share a single connection across fibers. But how would I go about
reusing DB connections when possible? By using ConnectionPool,
maybe? But I'm not quite sure how to use that.

In my modified version of the mysql driver there is a trivial MysqlDB
class that uses a ConnectionPool. lockConnection() returns a RAII
struct that makes sure that a single connection is not used twice.

Usually I would also mirror the methods of the Connection class for
convenience, but since I don't really use it myself, I didn't put so
much time into it yet.

https://github.com/rejectedsoftware/mysql-native/blob/master/source/mysql/db.d

So, if I'm understanding this right, ConnectionPool.lockConnection
creates and opens a new connection when the current fiber doesn't
already have an open connection, and returns an existing open connection
when the current fiber does have one?

Re: Minimizing new DB connections

Am 10/24/2012 6:59 PM, schrieb Nick Sabalausky:

On Wed, 24 Oct 2012 08:23:49 +0200
Sönke Ludwig sludwig@rejectedsoftware.com wrote:

Am 10/24/2012 5:01 AM, schrieb Nick Sabalausky:

To avoid the cost of establishing a new connection to a MySQL DB
on potentially every page request, I tried making one connection to
the DB upon startup of my vibe.d app and then use that one
connection for each request. Worked fine until I tried making
concurrent page requests, at which point I (perhaps unsurprisingly)
got a message about the wrong fiber accessing a connection and then
it died with an InvalidMemoryOperationError. (But annoyingly, I
can't seem to reproduce it now.)

So I realize that's probably not a smart thing to do anyway, to
share a single connection across fibers. But how would I go about
reusing DB connections when possible? By using ConnectionPool,
maybe? But I'm not quite sure how to use that.

In my modified version of the mysql driver there is a trivial MysqlDB
class that uses a ConnectionPool. lockConnection() returns a RAII
struct that makes sure that a single connection is not used twice.

Usually I would also mirror the methods of the Connection class for
convenience, but since I don't really use it myself, I didn't put so
much time into it yet.

https://github.com/rejectedsoftware/mysql-native/blob/master/source/mysql/db.d

So, if I'm understanding this right, ConnectionPool.lockConnection
creates and opens a new connection when the current fiber doesn't
already have an open connection, and returns an existing open connection
when the current fiber does have one?

It keeps a pool of connections and picks an unused one + calls acquire()
(or creates a new one if no unused connection exists). When it goes out
of scope (or better when the ref count drops to zero), it calls
release() on the connection so other fibers may call acquire().

So connections are always only temporarily pinned to a cetain fiber.

Re: Minimizing new DB connections

On Wed, 24 Oct 2012 20:14:15 +0200
Sönke Ludwig sludwig@rejectedsoftware.com wrote:

Am 10/24/2012 6:59 PM, schrieb Nick Sabalausky:

On Wed, 24 Oct 2012 08:23:49 +0200
Sönke Ludwig sludwig@rejectedsoftware.com wrote:

Am 10/24/2012 5:01 AM, schrieb Nick Sabalausky:

To avoid the cost of establishing a new connection to a MySQL DB
on potentially every page request, I tried making one connection
to the DB upon startup of my vibe.d app and then use that one
connection for each request. Worked fine until I tried making
concurrent page requests, at which point I (perhaps
unsurprisingly) got a message about the wrong fiber accessing a
connection and then it died with an InvalidMemoryOperationError.
(But annoyingly, I can't seem to reproduce it now.)

So I realize that's probably not a smart thing to do anyway, to
share a single connection across fibers. But how would I go about
reusing DB connections when possible? By using ConnectionPool,
maybe? But I'm not quite sure how to use that.

In my modified version of the mysql driver there is a trivial
MysqlDB class that uses a ConnectionPool. lockConnection()
returns a RAII struct that makes sure that a single connection is
not used twice.

Usually I would also mirror the methods of the Connection class for
convenience, but since I don't really use it myself, I didn't put
so much time into it yet.

https://github.com/rejectedsoftware/mysql-native/blob/master/source/mysql/db.d

So, if I'm understanding this right, ConnectionPool.lockConnection
creates and opens a new connection when the current fiber doesn't
already have an open connection, and returns an existing open
connection when the current fiber does have one?

It keeps a pool of connections and picks an unused one + calls
acquire() (or creates a new one if no unused connection exists). When
it goes out of scope (or better when the ref count drops to zero), it
calls release() on the connection so other fibers may call acquire().

So connections are always only temporarily pinned to a cetain fiber.

And I assume these unused connections can remain open while in the pool
and being aquired by another fiber, right? Sounds awesome and exactly
what I need :)

Re: Minimizing new DB connections

Am 10/24/2012 8:28 PM, schrieb Nick Sabalausky:

On Wed, 24 Oct 2012 20:14:15 +0200
Sönke Ludwig sludwig@rejectedsoftware.com wrote:

Am 10/24/2012 6:59 PM, schrieb Nick Sabalausky:

On Wed, 24 Oct 2012 08:23:49 +0200
Sönke Ludwig sludwig@rejectedsoftware.com wrote:

Am 10/24/2012 5:01 AM, schrieb Nick Sabalausky:

To avoid the cost of establishing a new connection to a MySQL DB
on potentially every page request, I tried making one connection
to the DB upon startup of my vibe.d app and then use that one
connection for each request. Worked fine until I tried making
concurrent page requests, at which point I (perhaps
unsurprisingly) got a message about the wrong fiber accessing a
connection and then it died with an InvalidMemoryOperationError.
(But annoyingly, I can't seem to reproduce it now.)

So I realize that's probably not a smart thing to do anyway, to
share a single connection across fibers. But how would I go about
reusing DB connections when possible? By using ConnectionPool,
maybe? But I'm not quite sure how to use that.

In my modified version of the mysql driver there is a trivial
MysqlDB class that uses a ConnectionPool. lockConnection()
returns a RAII struct that makes sure that a single connection is
not used twice.

Usually I would also mirror the methods of the Connection class for
convenience, but since I don't really use it myself, I didn't put
so much time into it yet.

https://github.com/rejectedsoftware/mysql-native/blob/master/source/mysql/db.d

So, if I'm understanding this right, ConnectionPool.lockConnection
creates and opens a new connection when the current fiber doesn't
already have an open connection, and returns an existing open
connection when the current fiber does have one?

It keeps a pool of connections and picks an unused one + calls
acquire() (or creates a new one if no unused connection exists). When
it goes out of scope (or better when the ref count drops to zero), it
calls release() on the connection so other fibers may call acquire().

So connections are always only temporarily pinned to a cetain fiber.

And I assume these unused connections can remain open while in the pool
and being aquired by another fiber, right? Sounds awesome and exactly
what I need :)

Yep! They'll stay open until something forcably closes them. The
downside, I think, is that the MySQL driver does not detect when a
connection is broken and does not restart it, this is something that
still needs to be implemented to make it more robust.

Re: Minimizing new DB connections

On Wed, 24 Oct 2012 21:13:12 +0200
Sönke Ludwig sludwig@rejectedsoftware.com wrote:

Yep! They'll stay open until something forcably closes them. The
downside, I think, is that the MySQL driver does not detect when a
connection is broken and does not restart it, this is something that
still needs to be implemented to make it more robust.

Is there a recommended way to check if the connection is still open? I
don't see any property like isopen(), just an internal _open flag which
I'm guessing is probably not guaranteed to be updated if the connection
breaks in ways other than calling close().

Re: Minimizing new DB connections

On Wed, 24 Oct 2012 16:13:41 -0400
Nick Sabalausky SeeWebsiteToContactMe@semitwist.com wrote:

On Wed, 24 Oct 2012 21:13:12 +0200
Sönke Ludwig sludwig@rejectedsoftware.com wrote:

Yep! They'll stay open until something forcably closes them. The
downside, I think, is that the MySQL driver does not detect when a
connection is broken and does not restart it, this is something that
still needs to be implemented to make it more robust.

Is there a recommended way to check if the connection is still open?

Like, just try to use it and then catch/inspect any resulting MySQL
exception?

I
don't see any property like isopen(), just an internal _open flag
which I'm guessing is probably not guaranteed to be updated if the
connection breaks in ways other than calling close().

Re: Minimizing new DB connections

Am 10/24/2012 10:19 PM, schrieb Nick Sabalausky:

On Wed, 24 Oct 2012 16:13:41 -0400
Nick Sabalausky SeeWebsiteToContactMe@semitwist.com wrote:

On Wed, 24 Oct 2012 21:13:12 +0200
Sönke Ludwig sludwig@rejectedsoftware.com wrote:

Yep! They'll stay open until something forcably closes them. The
downside, I think, is that the MySQL driver does not detect when a
connection is broken and does not restart it, this is something that
still needs to be implemented to make it more robust.

Is there a recommended way to check if the connection is still open?

Like, just try to use it and then catch/inspect any resulting MySQL
exception?

I
don't see any property like isopen(), just an internal _open flag
which I'm guessing is probably not guaranteed to be updated if the
connection breaks in ways other than calling close().

For the MongoDB driver I defined the connection to be always open. It
will reconnect automatically, if it detects a connection loss right
before a command is issued and throw if either the connection attempt
fails, or if the connection fails while a command message is sent or
received.

Another possibility would of course be to put that logic in the
ConnectionPool, if that is used for every connection anyway, this would
require less overall code. But first I'll dig a bit in the MySQL driver
code and see if there is a convenient place for this.