Saya akan merekomendasikan mencari info di milis PostgreSQL tentang desain multi-penyewa. Ada banyak diskusi di sana, dan jawabannya bermuara pada "tergantung". Ada trade-off antara jaminan isolasi, performa, dan perawatan.
Pendekatan umum adalah menggunakan database tunggal, tetapi satu skema (namespace) per pelanggan dengan struktur tabel yang sama di setiap skema, ditambah skema bersama atau umum untuk data yang sama di semua skema. Skema PostgreSQL seperti "database" MySQL di mana Anda dapat melakukan kueri di seluruh skema yang berbeda tetapi mereka diisolasi secara default. Dengan data pelanggan dalam skema terpisah, Anda dapat menggunakan search_path
pengaturan, biasanya melalui ALTER USER
customername SET search_path = 'customerschema, sharedschema'
untuk memastikan setiap pelanggan melihat data mereka dan hanya data mereka.
Untuk perlindungan tambahan, Anda harus REVOKE
ALL FROM SCHEMA customerschema FROM public
lalu GRANT
ALL ON SCHEMA customerschema TO thecustomer
jadi mereka satu-satunya yang memiliki akses ke sana, melakukan hal yang sama untuk setiap tabel mereka. Kumpulan koneksi Anda kemudian dapat masuk dengan akun pengguna tetap yang tidak GRANT
ed akses ke skema pelanggan mana pun tetapi memiliki hak untuk SET ROLE
untuk menjadi pelanggan mana pun. (Lakukan itu dengan memberi mereka keanggotaan dari setiap peran pelanggan dengan set NOINHERIT sehingga hak harus diklaim secara eksplisit melalui SET ROLE
). Koneksi harus segera SET ROLE
kepada pelanggan yang saat ini beroperasi sebagai. Itu akan memungkinkan Anda untuk menghindari overhead membuat koneksi baru untuk setiap pelanggan sambil mempertahankan perlindungan yang kuat terhadap kesalahan programmer yang mengarah ke akses ke data pelanggan yang salah. Selama kumpulan melakukan DISCARD ALL
dan/atau RESET ROLE
sebelum membagikan koneksi ke klien berikutnya, itu akan memberi Anda isolasi yang sangat kuat tanpa frustrasi koneksi individual per pengguna.
Jika lingkungan aplikasi web Anda tidak memiliki kumpulan koneksi bawaan yang layak (misalnya, Anda menggunakan PHP dengan koneksi persisten) maka Anda benar-benar perlu menempatkan kumpulan koneksi yang baik
di tempat antara Pg dan server web, karena terlalu banyak koneksi ke backend akan merusak kinerja Anda. PgBouncer
dan PgPool-II
adalah opsi terbaik, dan dengan mudah dapat melakukan DISCARD ALL
dan RESET ROLE
untuk Anda selama pengalihan koneksi.
Kelemahan utama dari pendekatan ini adalah overhead dengan mempertahankan banyak tabel, karena set dasar tabel non-bersama Anda dikloning untuk setiap pelanggan. Ini akan bertambah seiring bertambahnya jumlah pelanggan, ke titik di mana banyaknya tabel untuk diperiksa selama autovacuum berjalan mulai menjadi mahal dan di mana operasi apa pun yang diskalakan berdasarkan jumlah total tabel di DB melambat. Ini lebih merupakan masalah jika Anda berpikir untuk memiliki ribuan atau puluhan ribu pelanggan dalam DB yang sama, tetapi saya sangat menyarankan Anda melakukan beberapa tes penskalaan dengan desain ini menggunakan data dummy sebelum menerapkannya.
Pendekatan yang ideal kemungkinan adalah tabel tunggal dengan keamanan tingkat baris otomatis yang mengontrol visibilitas tupel, tetapi sayangnya itu adalah sesuatu yang belum dimiliki PostgreSQL. Sepertinya sedang dalam proses berkat pekerjaan SEPostgreSQL yang menambahkan infrastruktur dan API yang sesuai, tetapi tidak dalam 9.1.