Pertanyaan Di Django, bagaimana cara mengulang pembacaan untuk suatu transaksi?


Saya memiliki fungsi, yang melakukan beberapa kueri pada kumpulan data yang sama dan saya ingin memastikan semua kueri akan melihat data yang sama persis.

Dalam hal SQL, ini berarti level isolasi BACA ULANG untuk database yang mendukungnya. Saya tidak keberatan memiliki tingkat yang lebih tinggi atau bahkan kuncian lengkap jika database tidak mampu.

Sejauh yang saya lihat, ini tidak terjadi. Yaitu. jika saya menjalankan sesuatu seperti kode ini dalam satu shell Python:

with transaction.atomic():
    for t in range(0, 60):
        print("{0}: {1}".format(t, MyModel.objects.count()))
        time.sleep(1)

Segera setelah saya lakukan MyModel.objects.create(...) di lain, nilai yang terlihat oleh loop berjalan meningkat segera. Itulah tepatnya yang ingin saya hindari. Tes lebih lanjut menunjukkan perilaku sesuai tingkat KOMITMEN BACA, yang terlalu longgar untuk selera saya.

Saya juga ingin menekankan intinya, saya ingin tingkat isolasi yang lebih ketat hanya untuk satu fungsi, bukan untuk keseluruhan proyek.

Apa pilihan terbaik saya untuk mencapai ini?

Dalam kasus khusus saya, satu-satunya basis data yang saya pedulikan adalah PostgreSQL 9.3+, tetapi saya juga ingin beberapa kompatibilitas dengan SQLite3 yang dalam hal ini bahkan mengunci seluruh basis data secara keseluruhan tidak masalah bagi saya. Namun, jelas, semakin umum solusinya, semakin disukai itu.


8
2018-06-20 15:31


asal


Jawaban:


Anda benar, tingkat isolasi transaksi default dalam postgres adalah BACA DIKOMITMEN. Anda dapat dengan mudah mengubahnya dalam pengaturan untuk menguji apakah itu sesuai dengan kebutuhan Anda: https://docs.djangoproject.com/en/1.8/ref/databases/#isolation-level

Juga saya ragu Anda akan menghadapi beberapa masalah kinerja karena postgres beroperasi sangat efisien saat bekerja dengan transaksi. Bahkan dalam mode SERIALIZABLE. Juga mysql memiliki level isolasi default REEATABLE READ dan seperti yang kita lihat itu juga tidak merusak performa.

Pokoknya Anda dapat mengatur mode isolasi secara manual kapan pun Anda membutuhkannya seperti ini: http://initd.org/psycopg/docs/extensions.html#isolation-level-constants

Untuk mengatur tingkat isolasi transaksi khusus, Anda dapat mencoba sedikit seperti:

from django.db import connection

with transaction.atomic():
    cursor = connection.cursor()
    cursor.execute('SET TRANSACTION ISOLATION LEVEL REPEATABLE READ')
    # logic

Juga saya sarankan Anda untuk mengubah mode default di pengaturan pertama (jika Anda bisa). Kemudian jika sesuai dengan kebutuhan Anda, Anda dapat menghapusnya dan memodifikasi kode di tempat-tempat khusus.


8
2018-06-20 16:44