-
Notifications
You must be signed in to change notification settings - Fork 18k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: database/sql: support creating a *sql.DB directly from a driver.Driver and dsn. #20268
Comments
I'm not sure I understand. @kardianos? Can't drivers define their own opener funcs in their own packages already? |
Let me think about this and look into your motivating examples. |
@james-lawrence If I understand you correctly, you are looking for a way to create a connection pool (*sql.DB) but still be able to pass in option parameters when you are creating it. The following isn't a serious proposal, but a rephasing to ensure I understand what you feel is missing:
Is this another way of expressing your requested end state? Again, this is stated mainly for my own understanding, not a proposal at this time. |
it could be viewed that way yes. |
Thanks for confirming. Before considering this further, I would want some driver maintainers to weigh in on this. Can you link to discussions with driver maintainers about this? Or ask them to comment on this issue? |
sure thing. I'll point them in this direction. |
Waiting for more input. |
sorry, didn't get around to getting to other driver maintainers this weekend. |
Without weighing in on any of the proposed solutions, I can confirm that this is an issue for pgx. At the moment there are a number of options that can't be easily be handled with a database URL or DSN such as TLS configuration, logging, custom dialer, and an after connect hook. In the current version of pgx, the approach of registering a new driver for each different config was used. However, there is no way to unregister a driver. This means the driver and the associated pgx data structures can never be garbage collected. For one user who was apparently opening and closing databases a great many times this caused a problem (unusual behavior to be sure, but it still shouldn't break). In the upcoming version, I'm taking an approach similar to the MySQL driver in that pgx maintains a configuration registry and can encode a reference to that registry in a connection string. Then when Driver.Open is called the configuration can be extracted. The usage looks like so:
|
@jackc If SQLite, pgx, and mysql all use workarounds for the lack of parameters to pass in, I'm interested in thoughts any of the database drivers have in a less hacky way to pass in params. |
Basically, I'm +1 on this proposal. Another API design option is prohibit DSN. Driver is fully configured at beginning.
|
I think @methane's API would do everything pgx would need. |
@kardianos anything else we need to do here to move forward? I'm happy to do the work for this. |
Feel free to send a CL, though it won't be able to be merged until the tree opens again. |
It sounds like @kardianos is OK with @methane's proposal of adding type Connector and func NewFromConnector, although maybe that should have a shorter name. I am a little confused about this comment though:
To be clear, we cannot break all the code that is using Open with syntaxes that exist today. Assuming we're not talking about breaking that code, and based on @kardianos being happy, proposal accepted. |
@methane was just referring to the fact that if you use open it requires
reparsing the DNS string each time the proposal won't break the open method.
|
Change https://golang.org/cl/53430 mentions this issue: |
I also strongly support @methane's general approach. While I don't see any benefit in the proposal in the first post (one still has to use different driver instances, which seems like a bad workaround to me, if I understand it correctly?), the other proposal is very flexible and also avoids useless DSN string parsing (and thus also allocations) every time a connection is opened. In the MySQL driver we already provide a If this is the intended approach, I would however define the type Connector interface {
Connect() (driver.Conn, error)
} This way a user could directly pass the instance of the Edit: I just saw that https://golang.org/cl/53430 is already pretty much that. +1 for that CL in that case. |
We should also provide way to stop connectionOpener. |
@mattn Do you mean adding Context like this? type Connector interface {
Connect(ctx context.Context) (driver.Conn, error)
} |
@methane Yes, it is. |
Not sure I agree with that, the drivers could just as easily allow a ConnectTimeout configuration option and handle it internally. no reason to expose a context in this manner. |
I'm +0.5 to adding context to Connect(). Current database/sql won't use context for opening connection, because connections But if future But I don't know Google's future plan. |
Could you sketch/expand on that concept of a sync open that bypasses the
pool?
…On Thu, Aug 24, 2017, 00:29 INADA Naoki ***@***.***> wrote:
I'm +0.5 to adding context to Connect().
Current database/sql won't use context for opening connection, because
connections
are created asynchronously in the connectionOpener goroutine.
But if future database/sql adds support bypassing pool and use connection
synchronously,
it can be beneficial.
It will be good for GAE/Go because GAE/Go requires request context to open
and use TCP connection.
But I don't know Google's future plan.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#20268 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAuFsRnohQ-N26ysZmSKv8MQDIyZ30T8ks5sbSZFgaJpZM4NS21O>
.
|
For user level, it's very similar to
db.NewConn(ctx) uses |
What is the advantage over having the individual driver just implement this? why does it belong in the sql package? edit: I'm just curious why this is useful? and why it should be implemented by the sql.DB when Conn(ctx) already exists? I don't see any added benefit. |
As I noted above, GAE/Go has special requirements: context bound to request is needed to use TCP. Another reason is flexibility. Currently, But I'm not sure it's enough reason or not. So I'm only +0.5. |
@methane I don't think any sort of database pool will work on GAE classic. As you noted, the socket type requires a valid Go context, but contexts are scoped to a request. So in this case you wouldn't open a connection pool, just individual connections as you needed them. However, GAE flexible removes this restriction and you can use the standard "database/sql" package as it is today. I'm not currently too hot to add db.NewConn(ctx), though it is interesting to be honest (allowing the user to create a connection outside the connection pool). I would need a more convincing use case before it gets added however. I am interested in adding context to Connect. I'm not sure if it will be useful or not, so I'll need to look at the code some more to determine that. FYI, I'm happy with the CL. I may merge it and decide about if Connect should have a context in the next month. |
I'm recommending that Connect include a context. There are two current paths that open a connection: a background opener without a context (no associated request) and a open/connect command inline with the request with a context (because it does come from a request). This will allow the driver to abort a dial if the context is cancled and return promptly. |
What's the benefit of cancelling the connection instead of just putting it in the pool if it isn't needed anymore when it is finally open? Unless I miss something here, adding a Context would only make sense if there is some way to open a single connection directly. |
It would let the client get back to doing what ever it needs to urgently do.
Without: a connection may have a dial timeout of 10s, but the ctx will get
canceled in 3ms. The context canceled, the dial aborted, and the client is
allowed to resume work.
…On Thu, Aug 31, 2017 at 10:54 AM Julien Schmidt ***@***.***> wrote:
What's the benefit of cancelling the connection instead of just putting it
in the pool if it isn't needed anymore when it is finally open?
The same might happen with the next request, but then a connection from
the pool is available.
Unless I oversee something here, adding a Context would only make sense if
there is some way to open a single connection directly.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#20268 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAuFsfDgF0URPn-VTOlRm7dElSuI27owks5sdvNmgaJpZM4NS21O>
.
|
I assume that by "client" you mean the user of the database/sql interface (and not the driver itself)? You are right, a context makes sense in situations where no connection is available and a new connection is opened synchronously. |
Yes, that is the client I was speaking of.
I agree. We could do it, but I don't think it would pay for itself in terms
of added complexity or performance.
…On Thu, Aug 31, 2017 at 12:20 PM Julien Schmidt ***@***.***> wrote:
I assume that by "client" you mean the user the user of the database/sql
interface (and not the driver itself)?
You are right, a context makes sense in situations where no connection is
available and a new connection is opened synchronously
<https://github.com/golang/go/blob/e9b9dfe3f71a8b9f5006616f877836c67eb4fba0/src/database/sql/sql.go#L999>
.
Ideally, the function would return without waiting for the driver, while
the driver asynchronously keeps establishing the connection which then is
put in the pool when it is open.
Otherwise it might lead to situations where the driver is repeatedly asked
to open new connections which are then cancelled, resulting in a lot of
wasted resources. But I doubt that that could be implemented in a useful
way, as the connection then had to be always opened by another goroutine,
adding unnecessary synchronization overhead.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#20268 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAuFsdmKAuAkabkLNFjZX9Grv5yXOB0oks5sdweAgaJpZM4NS21O>
.
|
so verdict is to pass on adding the context? I agree with julien's statements it being a pain to implement in a useful manner. |
The verdict is to add Context as in Daniel's comments on the CL. |
sometimes drivers expose functionality that doesn't make sense to handle via the DSN and would be painful/impossible to setup, using PGX as an example:
splitting sql.Open into two methods solves the above issues with minimal changes to the runtime.
for reference here is the current open code:
The text was updated successfully, but these errors were encountered: