Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Aplikasi Django multi-penyewa:mengubah koneksi basis data per permintaan?

Saya telah melakukan sesuatu yang serupa yang paling dekat dengan poin 1, tetapi alih-alih menggunakan middleware untuk mengatur koneksi default, router basis data Django digunakan. Ini memungkinkan logika aplikasi untuk menggunakan sejumlah database jika diperlukan untuk setiap permintaan. Terserah logika aplikasi untuk memilih database yang sesuai untuk setiap kueri, dan ini adalah kelemahan besar dari pendekatan ini.

Dengan pengaturan ini, semua database terdaftar di settings.DATABASES , termasuk database yang dapat dibagikan di antara pelanggan. Setiap model khusus pelanggan ditempatkan dalam aplikasi Django yang memiliki label aplikasi tertentu.

misalnya. Kelas berikut mendefinisikan model yang ada di semua database pelanggan.

class MyModel(Model):
    ....
    class Meta:
        app_label = 'customer_records'
        managed = False

Sebuah router database ditempatkan di settings.DATABASE_ROUTERS rantai untuk merutekan permintaan basis data dengan app_label , kira-kira seperti ini (bukan contoh lengkap):

class AppLabelRouter(object):
    def get_customer_db(self, model):
        # Route models belonging to 'myapp' to the 'shared_db' database, irrespective
        # of customer.
        if model._meta.app_label == 'myapp':
            return 'shared_db'
        if model._meta.app_label == 'customer_records':
            customer_db = thread_local_data.current_customer_db()
            if customer_db is not None:
                return customer_db

            raise Exception("No customer database selected")
        return None

    def db_for_read(self, model, **hints):
        return self.get_customer_db(model, **hints)

    def db_for_write(self, model, **hints):
        return self.get_customer_db(model, **hints)

Bagian khusus dari router ini adalah thread_local_data.current_customer_db() panggilan. Sebelum router dijalankan, pemanggil/aplikasi harus sudah mengatur db pelanggan saat ini di thread_local_data . Manajer konteks Python dapat digunakan untuk tujuan ini untuk mendorong/memunculkan database pelanggan saat ini.

Dengan semua ini dikonfigurasi, kode aplikasi kemudian terlihat seperti ini, di mana UseCustomerDatabase adalah manajer konteks untuk mendorong/meletakkan nama basis data pelanggan saat ini ke dalam thread_local_data sehingga thread_local_data.current_customer_db() akan mengembalikan nama database yang benar ketika router akhirnya terkena:

class MyView(DetailView):
    def get_object(self):
        db_name = determine_customer_db_to_use(self.request) 
        with UseCustomerDatabase(db_name):
            return MyModel.object.get(pk=1)

Ini adalah pengaturan yang cukup rumit. Ini berhasil, tetapi saya akan mencoba merangkum apa yang saya lihat sebagai kelebihan dan kekurangan:

Keuntungan

  • Pemilihan database bersifat fleksibel. Ini memungkinkan beberapa database untuk digunakan dalam satu kueri, baik database khusus pelanggan maupun database bersama dapat digunakan dalam satu permintaan.
  • Pemilihan basis data bersifat eksplisit (tidak yakin apakah ini merupakan keuntungan atau kerugian). Jika Anda mencoba menjalankan kueri yang mengenai database pelanggan tetapi aplikasi tidak memilihnya, pengecualian akan terjadi yang menunjukkan kesalahan pemrograman.
  • Menggunakan router database memungkinkan database yang berbeda ada pada host yang berbeda, daripada mengandalkan USE db; pernyataan yang menebak bahwa semua database dapat diakses melalui satu koneksi.

Kekurangan

  • Pengaturannya rumit, dan ada beberapa lapisan yang terlibat untuk membuatnya berfungsi.
  • Kebutuhan dan penggunaan data lokal utas tidak jelas.
  • Tampilan dipenuhi dengan kode pemilihan basis data. Ini dapat diabstraksikan menggunakan tampilan berbasis kelas untuk secara otomatis memilih database berdasarkan parameter permintaan dengan cara yang sama seperti middleware akan memilih database default.
  • Pengelola konteks untuk memilih database harus membungkus set kueri sedemikian rupa sehingga pengelola konteks masih aktif saat kueri dievaluasi.

Saran

Jika Anda menginginkan akses basis data yang fleksibel, saya sarankan untuk menggunakan perute basis data Django. Gunakan Middleware atau Mixin tampilan yang secara otomatis mengatur database default untuk digunakan untuk koneksi berdasarkan parameter permintaan. Anda mungkin harus menggunakan utas data lokal untuk menyimpan database default yang akan digunakan sehingga ketika router terkena, router mengetahui database mana yang akan dirutekan. Ini memungkinkan Django untuk menggunakan koneksi persisten yang ada ke database (yang mungkin berada pada host yang berbeda jika diinginkan), dan memilih database untuk digunakan berdasarkan pengaturan perutean dalam permintaan.

Pendekatan ini juga memiliki keuntungan bahwa database untuk kueri dapat diganti jika diperlukan dengan menggunakan QuerySet using() fungsi untuk memilih database selain default.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana cara mendapatkan hari pertama setiap bulan yang sesuai di mysql?

  2. Kolom 'Perbarui Timestamp' MySQL - Pemicu

  3. Tampilkan subkategori wordpress saja

  4. hubungan banyak ke banyak

  5. Kapan menggunakan LEFT JOIN dan kapan menggunakan INNER JOIN?