diff --git a/docs/sources/administration/provisioning.md b/docs/sources/administration/provisioning.md index 50a2893a11a..862bee3dfe5 100644 --- a/docs/sources/administration/provisioning.md +++ b/docs/sources/administration/provisioning.md @@ -168,6 +168,9 @@ Since not all datasources have the same configuration settings we only have the | sslmode | string | PostgreSQL | SSLmode. 'disable', 'require', 'verify-ca' or 'verify-full' | | postgresVersion | number | PostgreSQL | Postgres version as a number (903/904/905/906/1000) meaning v9.3, v9.4, ..., v10 | | timescaledb | boolean | PostgreSQL | Enable usage of TimescaleDB extension | +| maxOpenConns | number | MySQL, PostgreSQL & MSSQL | Maximum number of open connections to the database (Grafana v5.4+) | +| maxIdleConns | number | MySQL, PostgreSQL & MSSQL | Maximum number of connections in the idle connection pool (Grafana v5.4+) | +| connMaxLifetime | number | MySQL, PostgreSQL & MSSQL | Maximum amount of time in seconds a connection may be reused (Grafana v5.4+) | #### Secure Json Data diff --git a/docs/sources/features/datasources/mssql.md b/docs/sources/features/datasources/mssql.md index a8399804344..4a3478b161a 100644 --- a/docs/sources/features/datasources/mssql.md +++ b/docs/sources/features/datasources/mssql.md @@ -32,6 +32,9 @@ Name | Description *Database* | Name of your MSSQL database. *User* | Database user's login/username *Password* | Database user's password +*Max open* | The maximum number of open connections to the database, default `unlimited` (Grafana v5.4+). +*Max idle* | The maximum number of connections in the idle connection pool, default `2` (Grafana v5.4+). +*Max lifetime* | The maximum amount of time in seconds a connection may be reused, default `14400`/4 hours (Grafana v5.4+). ### Min time interval @@ -585,6 +588,10 @@ datasources: url: localhost:1433 database: grafana user: grafana + jsonData: + maxOpenConns: 0 # Grafana v5.4+ + maxIdleConns: 2 # Grafana v5.4+ + connMaxLifetime: 14400 # Grafana v5.4+ secureJsonData: password: "Password!" diff --git a/docs/sources/features/datasources/mysql.md b/docs/sources/features/datasources/mysql.md index 590f4dec65e..988f632bff3 100644 --- a/docs/sources/features/datasources/mysql.md +++ b/docs/sources/features/datasources/mysql.md @@ -35,6 +35,9 @@ Name | Description *Database* | Name of your MySQL database. *User* | Database user's login/username *Password* | Database user's password +*Max open* | The maximum number of open connections to the database, default `unlimited` (Grafana v5.4+). +*Max idle* | The maximum number of connections in the idle connection pool, default `2` (Grafana v5.4+). +*Max lifetime* | The maximum amount of time in seconds a connection may be reused, default `14400`/4 hours. This should always be lower than configured [wait_timeout](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_wait_timeout) in MySQL (Grafana v5.4+). ### Min time interval @@ -316,4 +319,8 @@ datasources: database: grafana user: grafana password: password + jsonData: + maxOpenConns: 0 # Grafana v5.4+ + maxIdleConns: 2 # Grafana v5.4+ + connMaxLifetime: 14400 # Grafana v5.4+ ``` diff --git a/docs/sources/features/datasources/postgres.md b/docs/sources/features/datasources/postgres.md index 7076ff033b3..52f8804f27f 100644 --- a/docs/sources/features/datasources/postgres.md +++ b/docs/sources/features/datasources/postgres.md @@ -31,6 +31,9 @@ Name | Description *User* | Database user's login/username *Password* | Database user's password *SSL Mode* | This option determines whether or with what priority a secure SSL TCP/IP connection will be negotiated with the server. +*Max open* | The maximum number of open connections to the database, default `unlimited` (Grafana v5.4+). +*Max idle* | The maximum number of connections in the idle connection pool, default `2` (Grafana v5.4+). +*Max lifetime* | The maximum amount of time in seconds a connection may be reused, default `14400`/4 hours (Grafana v5.4+). *Version* | This option determines which functions are available in the query builder (only available in Grafana 5.3+). *TimescaleDB* | TimescaleDB is a time-series database built as a PostgreSQL extension. If enabled, Grafana will use `time_bucket` in the `$__timeGroup` macro and display TimescaleDB specific aggregate functions in the query builder (only available in Grafana 5.3+). @@ -374,6 +377,9 @@ datasources: password: "Password!" jsonData: sslmode: "disable" # disable/require/verify-ca/verify-full + maxOpenConns: 0 # Grafana v5.4+ + maxIdleConns: 2 # Grafana v5.4+ + connMaxLifetime: 14400 # Grafana v5.4+ postgresVersion: 903 # 903=9.3, 904=9.4, 905=9.5, 906=9.6, 1000=10 timescaledb: false ``` diff --git a/pkg/tsdb/sql_engine.go b/pkg/tsdb/sql_engine.go index 963a627994e..1a4e2bd3943 100644 --- a/pkg/tsdb/sql_engine.go +++ b/pkg/tsdb/sql_engine.go @@ -98,8 +98,12 @@ var NewSqlQueryEndpoint = func(config *SqlQueryEndpointConfiguration, rowTransfo return nil, err } - engine.SetMaxOpenConns(10) - engine.SetMaxIdleConns(10) + maxOpenConns := config.Datasource.JsonData.Get("maxOpenConns").MustInt(0) + engine.SetMaxOpenConns(maxOpenConns) + maxIdleConns := config.Datasource.JsonData.Get("maxIdleConns").MustInt(2) + engine.SetMaxIdleConns(maxIdleConns) + connMaxLifetime := config.Datasource.JsonData.Get("connMaxLifetime").MustInt(14400) + engine.SetConnMaxLifetime(time.Duration(connMaxLifetime) * time.Second) engineCache.versions[config.Datasource.Id] = config.Datasource.Version engineCache.cache[config.Datasource.Id] = engine @@ -116,9 +120,7 @@ func (e *sqlQueryEndpoint) Query(ctx context.Context, dsInfo *models.DataSource, Results: make(map[string]*QueryResult), } - session := e.engine.NewSession() - defer session.Close() - db := session.DB() + var wg sync.WaitGroup for _, query := range tsdbQuery.Queries { rawSQL := query.Model.Get("rawSql").MustString() @@ -145,31 +147,41 @@ func (e *sqlQueryEndpoint) Query(ctx context.Context, dsInfo *models.DataSource, queryResult.Meta.Set("sql", rawSQL) - rows, err := db.Query(rawSQL) - if err != nil { - queryResult.Error = err - continue - } + wg.Add(1) - defer rows.Close() + go func(rawSQL string, query *Query, queryResult *QueryResult) { + defer wg.Done() + session := e.engine.NewSession() + defer session.Close() + db := session.DB() - format := query.Model.Get("format").MustString("time_series") - - switch format { - case "time_series": - err := e.transformToTimeSeries(query, rows, queryResult, tsdbQuery) + rows, err := db.Query(rawSQL) if err != nil { queryResult.Error = err - continue + return } - case "table": - err := e.transformToTable(query, rows, queryResult, tsdbQuery) - if err != nil { - queryResult.Error = err - continue + + defer rows.Close() + + format := query.Model.Get("format").MustString("time_series") + + switch format { + case "time_series": + err := e.transformToTimeSeries(query, rows, queryResult, tsdbQuery) + if err != nil { + queryResult.Error = err + return + } + case "table": + err := e.transformToTable(query, rows, queryResult, tsdbQuery) + if err != nil { + queryResult.Error = err + return + } } - } + }(rawSQL, query, queryResult) } + wg.Wait() return result, nil } diff --git a/public/app/plugins/datasource/mssql/partials/config.html b/public/app/plugins/datasource/mssql/partials/config.html index f8a36502009..4cb42e90f7c 100644 --- a/public/app/plugins/datasource/mssql/partials/config.html +++ b/public/app/plugins/datasource/mssql/partials/config.html @@ -29,6 +29,37 @@ +Connection limits + +