Skip to content

Use query-less datasource validation by default #17582

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

Closed
ckoutsouridis opened this issue Jul 19, 2019 · 6 comments
Closed

Use query-less datasource validation by default #17582

ckoutsouridis opened this issue Jul 19, 2019 · 6 comments
Assignees
Labels
type: enhancement A general enhancement
Milestone

Comments

@ckoutsouridis
Copy link

ckoutsouridis commented Jul 19, 2019

To add a bit more context on why i ask this. We have noticed that in our database there are a lot of select 1 from dual queries. which is neither a heavy query or bad..but do we really need to run a query to validate the datasource?

isn't a simple (with the reasonable try-catch blocks of-course)

datasource.getConnections().close();

enough?

or for extra validation

datasource.getConnections().isValid();

both the above 2 approaches will result in the same behaviour as the existing one with better timeout handing in some jdbc drivers (for example for oracle).
Besides, all datasource pools, are already doing validation according to their configs in an optimal way.

for example have a look at micronaut's health indicator

single simple file, database agnostic.

I believe this will simplify a lot the health check, and dba's around the world will be happy as well

If the community does not feel comfortable enough with jdbc driver validation mechanisms in general ( i don't see why not) , maybe we could add a property to control whether datasourceHelathIndicator should run a query, or rely on the jdbc driver isValid method.

besides, this looks like a double config problem,
we specify in one place how hikari (personally i chose the isValid method of the jdbc driver) validates, and then there is the datasourceHealthIndicator which is overriding this validation scheme.

this probably fixes: #4391 . At least for oracle, as in oracle drivers, the connection.isValid() respects the timeout that is configured in the pool. Probably same applies in other jdbc drivers

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jul 19, 2019
@wilkinsona
Copy link
Member

both the above 2 approaches will result in the same behaviour as the existing one

This would not result in the same behaviour. For example, we know that we have users that are using a custom query to meet their interpretation of what it means for the DataSource to be healthy.

besides, this looks like a double config problem,
we specify in one place how hikari (personally i chose the isValid method of the jdbc driver) validates, and then there is the datasourceHealthIndicator which is overriding this validation scheme.

Let's consider providing an option to use isValid() in the health indicator. That should satisfy both use cases.

@ckoutsouridis
Copy link
Author

Thank you @wilkinsona. i would suggest to use the hikariCP approach.

In hikariCP if we don't specify a connection-test-query, the validation will be done against the connection.isValid() of the jdbc driver .

in the same way, if someone is not specifying a custom query for the healthIndicator, maybe it's better to just use the isValid().

Besides, if it's not a custom query the isValid and select 1 from * are kind of equivalent.

We should also keep in mind that if we configure the datasource with something like
spring.datasource.hikari.connection-test-query=test_my_db_query

Apart from some minor timing windows, this query will get executed by a simple datasource.getConnection()

@wilkinsona
Copy link
Member

Apart from some minor timing windows, this query will get executed by a simple datasource.getConnection()

We cannot be certain that is the case if the DataSource has been proxied. It's possible for a Connection returned from DataSource.getConnection() to be lazy and only actually retrieve a Connection from the pool when it's used.

@ckoutsouridis
Copy link
Author

ckoutsouridis commented Jul 19, 2019

interesting, well, i am not sure how all datasource pools work, but at lest for hikaricp, the pool will not release a connection unless it passes the validation stage (according to it's ALIVE_BYPASS_WINDOW_MS).

So with a default setup, if a connection is not used within 500ms, the connection validation will run just by a datasource.getConnection()

in fact, after debugging this, the pool validation query is executed by the healthIndicator, even before the check query, it is executed during this block:

	private String getProduct(Connection connection) throws SQLException {
		return connection.getMetaData().getDatabaseProductName();
	}

In any case, any improvement in this, would be welcome.

@ttddyy
Copy link
Contributor

ttddyy commented Oct 16, 2019

+1 for using isValid() on DataSourceHealthIndicator.

Currently, in our tracing, there are bunch of SELECT 1 traces.
So, we need to exclude SELECT 1 on tracing configuration for jdbc instrumentation.
Such traces affect rate limit/capacity for the tracing service.

I like the idea that if test query is specified, then use the query; otherwise use isValid.
Though, it wouldn't really match with current design which retrieves default validation query from DatabaseDriver#validationQuery when query is not specified.

According to hikari documentation:

connectionTestQuery
If your driver supports JDBC4 we strongly recommend not setting this property. This is for "legacy" drivers that do not support the JDBC4 Connection.isValid() API. ...

We introduced similar in R2DBC-SPI, Connection#validate. This is because driver knows better in current condition of the connection, and it may have internal optimal way to check the status of the connection rather than performing validation query.

@philwebb philwebb added for: team-attention An issue we'd like other members of the team to review type: enhancement A general enhancement and removed for: team-attention An issue we'd like other members of the team to review status: waiting-for-triage An issue we've not yet triaged labels Oct 22, 2019
@philwebb philwebb added this to the 2.3.x milestone Oct 23, 2019
@snicoll snicoll self-assigned this Dec 30, 2019
snicoll added a commit to snicoll/spring-boot that referenced this issue Dec 30, 2019
@snicoll
Copy link
Member

snicoll commented Dec 30, 2019

I've started to hack something and, given the different in behaviour, I am wondering if that wouldn't be better to have a completely separate implementation (see 89c73bc). Using Connection#isValid is very simple, does not require spring-jdbc on the classpath (as there is no need for JdbcTemplate) and mixing the two modes in the same implementation feels a bit confusing to me.

@snicoll snicoll modified the milestones: 2.3.x, 2.3.0.M3 Feb 18, 2020
@wilkinsona wilkinsona changed the title allow query-less datasource healthIndicator Use query-less datasource validation by default Mar 12, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

6 participants