Gerenciar conexões de banco de dados,Gerenciar conexões de banco de dados,Gerenciar conexões de banco de dados,Gerenciar conexões de banco de dados

Esta página fornece práticas recomendadas e exemplos de código específicos de linguagem para ajudar você a criar aplicativos que usam conexões de banco de dados do Cloud SQL de forma eficaz.

Estes exemplos são trechos de um aplicativo web completo disponível para você no GitHub. Saiba mais .

Para obter instruções passo a passo sobre como executar um aplicativo Web de exemplo conectado ao Cloud SQL, siga o link para seu ambiente:

Pools de conexão

Um pool de conexões é um cache de conexões de banco de dados que são compartilhadas e reutilizadas para melhorar a latência e o desempenho da conexão. Quando seu aplicativo precisa de uma conexão de banco de dados, ele pega uma emprestada do pool temporariamente; quando o aplicativo termina a conexão, ele a retorna ao pool, onde pode ser reutilizada na próxima vez que o aplicativo precisar de uma conexão de banco de dados.

Abrir e fechar conexões

Ao usar um pool de conexões, você deve abrir e fechar as conexões corretamente, para que elas sempre retornem ao pool quando você terminar de usá-las. Conexões não retornadas ou "vazadas" não são reutilizadas, o que desperdiça recursos e pode causar gargalos de desempenho para o seu aplicativo.

Pitão

# Preparing a statement before hand can help protect against injections.
stmt = sqlalchemy.text(
    "INSERT INTO votes (time_cast, candidate) VALUES (:time_cast, :candidate)"
)
try:
    # Using a with statement ensures that the connection is always released
    # back into the pool at the end of statement (even if an error occurs)
    with db.connect() as conn:
        conn.execute(stmt, parameters={"time_cast": time_cast, "candidate": team})
        conn.commit()
except Exception as e:
    # If something goes wrong, handle the error in this section. This might
    # involve retrying or adjusting parameters depending on the situation.
    # ...

Java

// Using a try-with-resources statement ensures that the connection is always released back
// into the pool at the end of the statement (even if an error occurs)
try (Connection conn = pool.getConnection()) {

  // PreparedStatements can be more efficient and project against injections.
  String stmt = "INSERT INTO votes (time_cast, candidate) VALUES (?, ?);";
  try (PreparedStatement voteStmt = conn.prepareStatement(stmt);) {
    voteStmt.setTimestamp(1, now);
    voteStmt.setString(2, team);

    // Finally, execute the statement. If it fails, an error will be thrown.
    voteStmt.execute();
  }
} catch (SQLException ex) {
  // If something goes wrong, handle the error in this section. This might involve retrying or
  // adjusting parameters depending on the situation.
  // ...
}

Node.js

/**
 * Insert a vote record into the database.
 *
 * @param {object} pool The Knex connection object.
 * @param {object} vote The vote record to insert.
 * @returns {Promise}
 */
const insertVote = async (pool, vote) => {
  try {
    return await pool('votes').insert(vote);
  } catch (err) {
    throw Error(err);
  }
};

C#

using Npgsql;
using System;

namespace CloudSql
{
    public class PostgreSqlTcp
    {
        public static NpgsqlConnectionStringBuilder NewPostgreSqlTCPConnectionString()
        {
            // Equivalent connection string:
            // "Uid=<DB_USER>;Pwd=<DB_PASS>;Host=<INSTANCE_HOST>;Database=<DB_NAME>;"
            var connectionString = new NpgsqlConnectionStringBuilder()
            {
                // Note: Saving credentials in environment variables is convenient, but not
                // secure - consider a more secure solution such as
                // Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
                // keep secrets safe.
                Host = Environment.GetEnvironmentVariable("INSTANCE_HOST"),     // e.g. '127.0.0.1'
                // Set Host to 'cloudsql' when deploying to App Engine Flexible environment
                Username = Environment.GetEnvironmentVariable("DB_USER"), // e.g. 'my-db-user'
                Password = Environment.GetEnvironmentVariable("DB_PASS"), // e.g. 'my-db-password'
                Database = Environment.GetEnvironmentVariable("DB_NAME"), // e.g. 'my-database'

                // The Cloud SQL proxy provides encryption between the proxy and instance.
                SslMode = SslMode.Disable,
            };
            connectionString.Pooling = true;
            // Specify additional properties here.
            return connectionString;
        }
    }
}

Ir

insertVote := "INSERT INTO votes(candidate, created_at) VALUES($1, NOW())"
_, err := db.Exec(insertVote, team)

Rubi

@vote = Vote.new candidate: candidate

# ActiveRecord creates and executes your SQL and automatically
# handles the opening and closing of the database connection.
if @vote.save
  render json: "Vote successfully cast for \"#{@vote.candidate}\" at #{@vote.time_cast} PST!"
else
  render json: @vote.errors, status: :unprocessable_entity
end

PHP

// Use prepared statements to guard against SQL injection.
$sql = 'INSERT INTO votes (time_cast, candidate) VALUES (NOW(), :voteValue)';

try {
    $statement = $conn->prepare($sql);
    $statement->bindParam('voteValue', $value);

    $res = $statement->execute();
} catch (PDOException $e) {
    throw new RuntimeException(
        'Could not insert vote into database. The PDO exception was ' .
        $e->getMessage(),
        $e->getCode(),
        $e
    );
}

Contagem de conexões

Cada conexão de banco de dados utiliza recursos do lado do cliente e do servidor. Além disso, o Cloud SQL impõe limites gerais de conexão que não podem ser excedidos. Criar e usar menos conexões reduz a sobrecarga e ajuda você a permanecer dentro do limite de conexões.

Pitão

# Pool size is the maximum number of permanent connections to keep.
pool_size=5,
# Temporarily exceeds the set pool_size if no connections are available.
max_overflow=2,
# The total number of concurrent connections for your application will be
# a total of pool_size and max_overflow.

Java

// maximumPoolSize limits the total number of concurrent connections this pool will keep. Ideal
// values for this setting are highly variable on app design, infrastructure, and database.
config.setMaximumPoolSize(5);
// minimumIdle is the minimum number of idle connections Hikari maintains in the pool.
// Additional connections will be established to meet this value unless the pool is full.
config.setMinimumIdle(5);

Node.js

// 'max' limits the total number of concurrent connections this pool will keep. Ideal
// values for this setting are highly variable on app design, infrastructure, and database.
config.pool.max = 5;
// 'min' is the minimum number of idle connections Knex maintains in the pool.
// Additional connections will be established to meet this value unless the pool is full.
config.pool.min = 5;

C#

// MaxPoolSize sets maximum number of connections allowed in the pool.
connectionString.MaxPoolSize = 5;
// MinPoolSize sets the minimum number of connections in the pool.
connectionString.MinPoolSize = 0;

Ir

// Set maximum number of connections in idle connection pool.
db.SetMaxIdleConns(5)

// Set maximum number of open connections to the database.
db.SetMaxOpenConns(7)

Rubi

# 'pool' is the maximum number of permanent connections to keep.
pool: 5

PHP

Atualmente, o PDO não oferece nenhuma funcionalidade para configurar limites de conexão.

Recuo exponencial

Se o seu aplicativo tentar se conectar ao banco de dados e não obtiver sucesso, o banco de dados poderá ficar temporariamente indisponível. Nesse caso, o envio repetido de solicitações de conexão desperdiça recursos. É preferível aguardar antes de enviar solicitações de conexão adicionais para permitir que o banco de dados fique acessível novamente. Usar um backoff exponencial ou outro mecanismo de atraso atinge esse objetivo.

Essa nova tentativa só faz sentido na primeira conexão ou na primeira captura de uma conexão do pool. Se ocorrerem erros no meio de uma transação, o aplicativo deverá realizar a nova tentativa, desde o início da transação. Portanto, mesmo que o pool esteja configurado corretamente, o aplicativo ainda poderá apresentar erros se as conexões forem perdidas.

Pitão

# SQLAlchemy automatically uses delays between failed connection attempts,
# but provides no arguments for configuration.

Java

// Hikari automatically delays between failed connection attempts, eventually reaching a
// maximum delay of `connectionTimeout / 2` between attempts.

Node.js

// 'knex' uses a built-in retry strategy which does not implement backoff.
// 'createRetryIntervalMillis' is how long to idle after failed connection creation before trying again
config.pool.createRetryIntervalMillis = 200; // 0.2 seconds

C#

Policy
    .Handle<NpgsqlException>()
    .WaitAndRetry(new[]
    {
        TimeSpan.FromSeconds(1),
        TimeSpan.FromSeconds(2),
        TimeSpan.FromSeconds(5)
    })
    .Execute(() => connection.Open());

Ir

O pacote de banco de dados/sql atualmente não oferece nenhuma funcionalidade para configurar o backoff exponencial.

Rubi

# ActiveRecord automatically uses delays between failed connection attempts,
# but provides no arguments for configuration.

PHP

Atualmente, o PDO não oferece nenhuma funcionalidade para configurar o backoff exponencial.

Tempo limite de conexão

Há muitos motivos pelos quais uma tentativa de conexão pode não ser bem-sucedida. A comunicação de rede nunca é garantida e o banco de dados pode ficar temporariamente indisponível. Certifique-se de que seu aplicativo trate conexões interrompidas ou malsucedidas com eficiência.

Pitão

# 'pool_timeout' is the maximum number of seconds to wait when retrieving a
# new connection from the pool. After the specified amount of time, an
# exception will be thrown.
pool_timeout=30,  # 30 seconds

Java

// setConnectionTimeout is the maximum number of milliseconds to wait for a connection checkout.
// Any attempt to retrieve a connection from this pool that exceeds the set limit will throw an
// SQLException.
config.setConnectionTimeout(10000); // 10 seconds
// idleTimeout is the maximum amount of time a connection can sit in the pool. Connections that
// sit idle for this many milliseconds are retried if minimumIdle is exceeded.
config.setIdleTimeout(600000); // 10 minutes

Node.js

// 'acquireTimeoutMillis' is the number of milliseconds before a timeout occurs when acquiring a
// connection from the pool. This is slightly different from connectionTimeout, because acquiring
// a pool connection does not always involve making a new connection, and may include multiple retries.
// when making a connection
config.pool.acquireTimeoutMillis = 60000; // 60 seconds
// 'createTimeoutMillis` is the maximum number of milliseconds to wait trying to establish an
// initial connection before retrying.
// After acquireTimeoutMillis has passed, a timeout exception will be thrown.
config.pool.createTimeoutMillis = 30000; // 30 seconds
// 'idleTimeoutMillis' is the number of milliseconds a connection must sit idle in the pool
// and not be checked out before it is automatically closed.
config.pool.idleTimeoutMillis = 600000; // 10 minutes

C#

// Timeout sets the time to wait (in seconds) while
// trying to establish a connection before terminating the attempt.
connectionString.Timeout = 15;

Ir

O pacote database/sql atualmente não oferece nenhuma funcionalidade para configurar o tempo limite de conexão. O tempo limite é configurado no nível do driver.

Rubi

# 'timeout' is the maximum number of seconds to wait when retrieving a
# new connection from the pool. After the specified amount of time, an
# ActiveRecord::ConnectionTimeoutError will be raised.
timeout: 5000

PHP

// Here we set the connection timeout to five seconds and ask PDO to
// throw an exception if any errors occur.
[
    PDO::ATTR_TIMEOUT => 5,
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]

Duração da conexão

Limitar o tempo de vida de uma conexão pode ajudar a evitar o acúmulo de conexões abandonadas. Você pode usar o pool de conexões para limitar o tempo de vida de suas conexões.

Pitão

# 'pool_recycle' is the maximum number of seconds a connection can persist.
# Connections that live longer than the specified amount of time will be
# re-established
pool_recycle=1800,  # 30 minutes

Java

// maxLifetime is the maximum possible lifetime of a connection in the pool. Connections that
// live longer than this many milliseconds will be closed and reestablished between uses. This
// value should be several minutes shorter than the database's timeout value to avoid unexpected
// terminations.
config.setMaxLifetime(1800000); // 30 minutes

Node.js

A biblioteca Node.js ' knex ' atualmente não oferece nenhuma funcionalidade para controlar a duração de uma conexão.

C#

// ConnectionIdleLifetime sets the time (in seconds) to wait before
// closing idle connections in the pool if the count of all
// connections exceeds MinPoolSize.
connectionString.ConnectionIdleLifetime = 300;

Ir

// Set Maximum time (in seconds) that a connection can remain open.
db.SetConnMaxLifetime(1800 * time.Second)

Rubi

Atualmente, o ActiveRecord não oferece nenhuma funcionalidade para controlar a duração de uma conexão.

PHP

Atualmente, o PDO não oferece nenhuma funcionalidade para controlar a duração de uma conexão.

Para ver o requerimento completo, clique no link abaixo.

Pitão

Veja o aplicativo completo para a linguagem de programação Python.

Java

Veja o aplicativo completo para a linguagem de programação Java.

Node.js

Veja o aplicativo completo para a linguagem de programação Node.js.

C#

Veja o aplicativo completo para a linguagem de programação C#.

Ir

Veja o aplicativo completo para a linguagem de programação Go.

Rubi

Veja o aplicativo completo para a linguagem de programação Ruby.

PHP

Veja o aplicativo completo para a linguagem de programação PHP.

O que vem a seguir