Gerenciar conexões de banco de dados

Veja nesta página práticas recomendadas e amostras de código específicas de cada linguagem para ajudar você a criar aplicativos que usam conexões de bancos de dados SQL de modo eficiente.

Essas amostras são trechos de um aplicativo padrão completo do App Engine disponível para você no GitHub. Saiba mais.

Pools de conexões

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 seu pool temporariamente. Assim que ele termina de usar a conexão, ela é devolvida ao pool para ser reutilizada da próxima vez em que o aplicativo precisar de uma conexão de banco de dados.

Python

# The SQLAlchemy engine will help manage interactions, including automatically
# managing a pool of connections to your database
db = sqlalchemy.create_engine(
    # Equivalent URL:
    # mysql+pymysql://<db_user>:<db_pass>@/<db_name>?unix_socket=/cloudsql/<cloud_sql_instance_name>
    sqlalchemy.engine.url.URL(
        drivername='mysql+pymysql',
        username=db_user,
        password=db_pass,
        database=db_name,
        query={
            'unix_socket': '/cloudsql/{}'.format(cloud_sql_connection_name)
        }
    ),
    # ... Specify additional properties here.
    # ...
)

Java

// The configuration object specifies behaviors for the connection pool.
HikariConfig config = new HikariConfig();

// Configure which instance and what database user to connect with.
config.setJdbcUrl(String.format("jdbc:mysql:///%s", DB_NAME));
config.setUsername(DB_USER); // e.g. "root", "postgres"
config.setPassword(DB_PASS); // e.g. "my-password"

// For Java users, the Cloud SQL JDBC Socket Factory can provide authenticated connections.
// See https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory for details.
config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.mysql.SocketFactory");
config.addDataSourceProperty("cloudSqlInstance", CLOUD_SQL_CONNECTION_NAME);
config.addDataSourceProperty("useSSL", "false");

// ... Specify additional connection properties here.
// ...

// Initialize the connection pool using the configuration object.
DataSource pool = new HikariDataSource(config);

Node.js

const pool = mysql.createPool({
  user: process.env.DB_USER, // e.g. 'my-db-user'
  password: process.env.DB_PASS, // e.g. 'my-db-password'
  database: process.env.DB_NAME, // e.g. 'my-database'
  // If connecting via unix domain socket, specify the path
  socketPath: `/cloudsql/${process.env.CLOUD_SQL_CONNECTION_NAME}`,
  // If connecting via TCP, enter the IP and port instead
  // host: 'localhost',
  // port: 3306,

  //...
});

Como iniciar e encerrar conexões

Ao usar um pool de conexões, é necessário iniciá-las e encerrá-las corretamente. Assim, as conexões sempre serão retornadas ao pool quando você terminar de usá-las. Conexões não retornadas ou "vazadas" não são reutilizadas, o que gera desperdício de recursos e potenciais gargalos de desempenho para seu aplicativo.

Python

# 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, time_cast=time_cast, candidate=team)
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.
  PreparedStatement voteStmt = conn.prepareStatement(
      "INSERT INTO votes (time_cast, candidate) VALUES (?, ?);");
  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

try {
  const stmt = 'INSERT INTO votes (time_cast, candidate) VALUES (?, ?)';
  // Pool.query automatically checks out, uses, and releases a connection
  // back into the pool, ensuring it is always returned successfully.
  await pool.query(stmt, [timestamp, team]);
} catch (err) {
  // If something goes wrong, handle the error in this section. This might
  // involve retrying or adjusting parameters depending on the situation.
  // ...
}

Número de conexões

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

Python

# 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

// 'connectionLimit' is the maximum number of connections the pool is allowed
// to keep at once.
connectionLimit: 5,

Espera exponencial

Se o aplicativo tentar se conectar ao banco de dados e não conseguir, o banco de dados poderá estar temporariamente indisponível. Nesse caso, enviar muitas solicitações de conexão simultâneas pode desperdiçar recursos adicionais do banco de dados e aumentar o tempo necessário para a recuperação. Usar retirada exponencial impede que o aplicativo envie um número inadequado de solicitações de conexão quando não puder se conectar ao banco de dados.

Python

# 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

// The mysql module automatically uses exponential delays between failed
// connection attempts.

Tempo limite de conexão

Existem muitas razões para a falha de uma tentativa de conexão. A comunicação de rede nunca é garantida, e pode ser que o banco de dados esteja temporariamente indisponível. Seu aplicativo precisa ser capaz de lidar com conexões interrompidas ou malsucedidas.

Python

# '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

// 'connectTimeout' is the maximum number of milliseconds before a timeout
// occurs during the initial connection to the database.
connectTimeout: 10000, // 10 seconds
// 'acquireTimeout' is the maximum number of milliseconds to wait when
// checking out a connection from the pool before a timeout error occurs.
acquireTimeout: 10000, // 10 seconds
// 'waitForConnections' determines the pool's action when no connections are
// free. If true, the request will queued and a connection will be presented
// when ready. If false, the pool will call back with an error.
waitForConnections: true, // Default: true
// 'queueLimit' is the maximum number of requests for connections the pool
// will queue at once before returning an error. If 0, there is no limit.
queueLimit: 0, // Default: 0

Duração da conexão

Limitar o tempo de vida de uma conexão pode ajudar a impedir o acúmulo de conexões abandonadas. Use o pool de conexões para limitar a vida útil da sua conexão.

Python

# 'pool_recycle' is the maximum number of seconds a connection can persist.
# Connections that live longer than the specified amount of time will be
# reestablished
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

Atualmente, a biblioteca 'mysql' do Node.js não oferece nenhuma funcionalidade para controlar a duração de uma conexão.

Para ver o aplicativo completo, clique no link abaixo.

Python

Veja o aplicativo completo da linguagem de programação Python.

Java

Ver o aplicativo completo da linguagem de programação Java.

Node.js

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

A seguir

Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…

Cloud SQL para MySQL