Chapter Koneksi dan Cursor menutup dengan janji membahas kapan koneksi dibuka dan ditutup dengan benar. Pertanyaan itu penting karena koneksi adalah resource nyata: file yang terkunci, memori yang terpakai, dan — pada database server — slot koneksi yang jumlahnya terbatas. Program yang membuka koneksi berkali-kali tanpa menutup, atau menahan satu koneksi selamanya sambil menggunjingkan database dari pemakai lain, adalah program yang lambat laun tersesat. Bab ini merumuskan kebiasaan pengelolaan koneksi yang bisa dibawa ke database apa pun.
Biaya Sebuah Koneksi #
Biaya membuka koneksi berbeda jauh antara SQLite dan database server:
| Aspek | SQLite | Database server (PostgreSQL, MySQL) |
|---|---|---|
| Membuka koneksi | membuka satu file, sangat murah | koneksi jaringan, autentikasi, sesi — mahal |
| Jumlah koneksi serentak | praktis tak dibatasi | dibatasi konfigurasi server, umumnya puluhan |
| Connection pooling | tidak dibutuhkan | standar di aplikasi web |
Untuk SQLite, aturannya longgar: buka koneksi per unit kerja — satu sesi CLI, satu eksekusi skrip, satu test — lalu tutup. Untuk database server, membuka koneksi baru untuk setiap request web itu boros; aplikasi memakai connection pool: kumpulan koneksi yang dibuka sekali dan dipinjamkan bergantian.
Menutup dengan contextlib.closing #
Kebiasaan try/finally dari Chapter Koneksi dan Cursor bekerja, tetapi Python punya alat yang lebih rapi untuk objek yang punya method close(): contextlib.closing():
from contextlib import closing
import sqlite3
with closing(sqlite3.connect(":memory:")) as conn:
conn.execute("CREATE TABLE t (a)")
conn.execute("INSERT INTO t VALUES (1)")
conn.commit()
print("Baris di dalam blok:", conn.execute("SELECT COUNT(*) FROM t").fetchone()[0])
try:
conn.execute("SELECT 1")
except sqlite3.ProgrammingError as e:
print("Galat:", e)Output yang Dihasilkan:
Baris di dalam blok: 1
Galat: Cannot operate on a closed database.Blok with closing(...) menjamin conn.close() terpanggil bagaimana pun blok berakhir — termasuk saat exception. Percobaan query setelah blok membuktikan koneksi benar-benar tertutup. Ingat beda dua pola with pada SQLite:
| Pola | Yang dikelola | Tidak mengurus |
| with conn: | commit / rollback | penutupan |
| with closing(conn): | penutupan | commit / rollback |
Untuk mengelola keduanya sekaligus, keduanya disarangkan — with closing(connect(...)) as conn: di luar, with conn: di sekitar rangkaian perubahan.
Health Check Koneksi #
Pada aplikasi berumur panjang — daemon, worker antrean — koneksi bisa terputus diam-diam di tengah jalan. Pemeriksaan kesehatan termurah adalah query paling ringan yang ada: SELECT 1:
import sqlite3
def cek_kesehatan(conn):
try:
return conn.execute("SELECT 1").fetchone() == (1,)
except sqlite3.Error:
return False
conn = sqlite3.connect(":memory:")
print("Sebelum close :", cek_kesehatan(conn))
conn.close()
print("Setelah close :", cek_kesehatan(conn))Output yang Dihasilkan:
Sebelum close : True
Setelah close : FalseFungsi cek_kesehatan() menelan seluruh galat turunan sqlite3.Error dan melaporkan keadaan sebagai boolean — pola yang lazim pada pemantauan aplikasi berjalan (health check endpoint), karena pemanggil hanya butuh tahu “sehat atau tidak”, bukan bentuk galatnya. Pada database server, query SELECT 1 berperan sama: ringan di server dan cukup untuk membuktikan sesi masih hidup.
Timeout dan Batas Koneksi #
Ketika dua prosess menulis ke database SQLite yang sama, penulis kedua menunggu sampai penulis pertama selesai. Parameter timeout pada connect() mengatur berapa lama menunggu sebelum menyerah dengan galat “database is locked”:
import sqlite3
conn_default = sqlite3.connect(":memory:")
conn_cepat = sqlite3.connect(":memory:", timeout=2.5)
print("default :", conn_default.execute("PRAGMA busy_timeout").fetchone()[0], "ms")
print("timeout=2.5 :", conn_cepat.execute("PRAGMA busy_timeout").fetchone()[0], "ms")
conn_default.close()
conn_cepat.close()Output yang Dihasilkan:
default : 5000 ms
timeout=2.5 : 2500 msNilai timeout dalam detik disimpan SQLite sebagai busy timeout dalam milidetik — bawaan 5 detik. Naikkan nilai ini di aplikasi dengan banyak penulis serentak; turunkan bila lebih baik gagal cepat daripada menggantung request.
Dengan koneksi yang terkelola, tahap terakhir section ini memandang ke depan: kapan SQLite saja tidak cukup dan bagaimana wujud kode kita di PostgreSQL dan MySQL — materi Chapter Pengenalan PostgreSQL dan MySQL.