Optimis vs penguncian Pesimis

572

Saya mengerti perbedaan antara penguncian optimis dan pesimistis. Sekarang bisakah seseorang menjelaskan kepada saya kapan saya akan menggunakan salah satu dari mereka secara umum?

Dan apakah jawaban untuk pertanyaan ini berubah tergantung pada apakah saya menggunakan prosedur tersimpan atau tidak untuk melakukan kueri?

Tetapi hanya untuk memeriksa, optimis berarti "jangan mengunci meja saat membaca" dan pesimistis berarti "mengunci meja saat membaca."

Jason Baker
sumber
1
blog.couchbase.com/...
Frank Myat Thu
1
Itu adalah pertanyaan yang bagus terutama karena dalam serializability saya baca At any technique type conflicts should be detected and considered, with similar overhead for both materialized and non-materialized conflicts.
Little Alien
1
Di sini Anda dapat menemukan penjelasan yang bagus, di sini di SO, tentang apa konsep dasar Penguncian Optimis .
Diego Mazzaro

Jawaban:

812

Penguncian Optimis adalah strategi di mana Anda membaca catatan, mencatat nomor versi (metode lain untuk melakukan ini melibatkan tanggal, cap waktu atau checksum / hashes) dan memeriksa bahwa versi tidak berubah sebelum Anda menulis catatan kembali. Saat Anda menulis catatan kembali, Anda memfilter pembaruan pada versi untuk memastikan itu atom. (Yaitu belum diperbarui antara saat Anda memeriksa versi dan menulis catatan ke disk) dan memperbarui versi dalam satu pukulan.

Jika catatan kotor (yaitu versi berbeda dengan milik Anda), Anda membatalkan transaksi dan pengguna dapat memulai kembali.

Strategi ini paling berlaku untuk sistem volume tinggi dan arsitektur tiga tingkat di mana Anda tidak perlu menjaga koneksi ke database untuk sesi Anda. Dalam situasi ini klien tidak dapat benar-benar menjaga kunci basis data karena koneksi diambil dari kumpulan dan Anda mungkin tidak menggunakan koneksi yang sama dari satu akses ke yang berikutnya.

Penguncian Pesimis adalah ketika Anda mengunci catatan untuk penggunaan eksklusif Anda sampai Anda selesai dengan itu. Ini memiliki integritas yang jauh lebih baik daripada penguncian optimis tetapi mengharuskan Anda untuk berhati-hati dengan desain aplikasi Anda untuk menghindari Deadlock . Untuk menggunakan penguncian pesimistis Anda memerlukan koneksi langsung ke basis data (seperti yang biasanya terjadi pada aplikasi server klien dua tingkat ) atau ID transaksi yang tersedia secara eksternal yang dapat digunakan secara terpisah dari koneksi.

Dalam kasus terakhir Anda membuka transaksi dengan TxID dan kemudian menyambung kembali menggunakan ID itu. DBMS mempertahankan kunci dan memungkinkan Anda untuk mengambil kembali sesi melalui TxID. Ini adalah cara transaksi terdistribusi menggunakan protokol komit dua fase (seperti XA atau COM + Transaksi ) bekerja.

ConcernedOfTunbridgeWells
sumber
148
Penguncian yang optimis tidak harus menggunakan nomor versi. Strategi lain termasuk menggunakan (a) cap waktu atau (b) seluruh status baris itu sendiri. Strategi terakhir jelek tetapi menghindari perlunya kolom versi khusus, dalam kasus di mana Anda tidak dapat memodifikasi skema.
Andrew Swan
2
@geek - Protokol transaksi terdistribusi seperti XA memungkinkan pengidentifikasi transaksi terpisah untuk reticulated di sekitar satu atau lebih sistem. Jenis protokol ini memang memungkinkan kunci untuk digunakan melalui koneksi gabungan karena pengidentifikasi transaksi dipisahkan dari sesi dan diberikan secara eksplisit. Namun, hal ini menimbulkan beberapa overhead dan rentan terhadap kebocoran kunci dan pengidentifikasi transaksi jika aplikasi Anda tidak teliti dalam melacaknya. Ini adalah solusi yang jauh lebih berat.
ConcernedOfTunbridgeWells
22
@supercat - Jangan setuju bahwa penguncian optimis kurang dari 100% akurat - asalkan memeriksa semua catatan input untuk transaksi yang harus tetap tidak dimodifikasi untuk durasi, itu seakurat penguncian pesimis (pilih untuk gaya pembaruan) pada mereka catatan yang sama. Perbedaan utama adalah bahwa penguncian optimis menimbulkan biaya hanya jika ada konflik, sedangkan penguncian pesimistis telah mengurangi overhead pada konflik. Jadi optimis adalah yang terbaik dalam kasus di mana sebagian besar transaksi tidak bertentangan - yang saya harap biasanya terjadi pada sebagian besar aplikasi.
RichVel
2
@ Legends - Menggunakan penguncian optimsitic tentu akan menjadi strategi yang tepat untuk aplikasi web.
ConcernedOfTunbridgeWells
2
Anda harus menyebutkan bahwa pilihan juga tergantung pada rasio baca dan tulis: jika aplikasi Anda terutama merupakan aplikasi hanya-baca oleh banyak pengguna, dan terkadang Anda menulis data, daripada menggunakan penguncian yang optimis. StackOverflow, misalnya, memiliki banyak orang membaca halaman, dan terkadang seseorang mengeditnya: dalam penguncian pesimistis, siapa yang akan mendapatkan kunci? yang pertama? Dalam penguncian optimis, orang yang ingin mengedit halaman dapat melakukannya selama ia memiliki versi terakhirnya.
jehon
177

Penguncian optimis digunakan ketika Anda tidak mengharapkan banyak tabrakan. Biayanya lebih rendah untuk melakukan operasi normal tetapi jika tabrakan terjadi, Anda akan membayar harga yang lebih tinggi untuk menyelesaikannya karena transaksi dibatalkan.

Penguncian pesimis digunakan ketika tabrakan diantisipasi. Transaksi yang akan melanggar sinkronisasi hanya diblokir.

Untuk memilih mekanisme penguncian yang tepat, Anda harus memperkirakan jumlah bacaan dan tulisan dan rencanakan dengan tepat.

Ilya Kochetov
sumber
Dalam kasus normal, pernyataannya sempurna tetapi dalam kasus khusus di mana Anda dapat mengelola operasi CAS yang memungkinkan ketidaktepatan seperti @skaffman yang disebutkan dalam jawaban, saya akan mengatakan itu sangat tergantung.
Dengar
75

Optimis berasumsi bahwa tidak ada yang akan berubah saat Anda membacanya.

Pesimistis mengasumsikan bahwa sesuatu akan dan akan menguncinya.

Jika tidak penting data dibaca dengan sempurna, gunakan optimis. Anda mungkin membaca 'kotor' yang aneh - tetapi jauh lebih kecil kemungkinannya menghasilkan kebuntuan dan sejenisnya.

Sebagian besar aplikasi web baik-baik saja dengan pembacaan yang kotor - pada kesempatan yang jarang, data tidak persis sesuai dengan penghitungan ulang berikutnya.

Untuk operasi data yang tepat (seperti dalam banyak transaksi keuangan) gunakan pesimistis. Sangat penting bahwa data dibaca secara akurat, tanpa perubahan yang tidak ditampilkan - overhead penguncian ekstra sepadan.

Oh, dan Microsoft SQL server default untuk penguncian halaman - pada dasarnya baris yang Anda baca dan beberapa sisi. Penguncian baris lebih akurat tetapi jauh lebih lambat. Seringkali ada baiknya Anda mengatur transaksi Anda menjadi read-commit atau no-lock untuk menghindari kebuntuan saat membaca.

Keith
sumber
Penguncian Optimis JPA memungkinkan Anda untuk menjamin konsistensi baca.
Gili
4
Konsistensi baca merupakan masalah tersendiri - dengan PostgreSQL, Oracle, dan banyak basis data lainnya, Anda mendapatkan tampilan data yang konsisten terlepas dari pembaruan apa pun yang belum dilakukan, dan tidak terpengaruh bahkan oleh kunci baris eksklusif.
RichVel
Saya harus setuju dengan @RichVel. Di satu sisi, saya dapat melihat bagaimana penguncian pesimistis dapat mencegah pembacaan kotor jika tingkat isolasi transaksi Anda BACA TIDAK DIKUMPULKAN. Tetapi menyesatkan untuk mengatakan bahwa penguncian optimis rentan terhadap pembacaan kotor tanpa menyebutkan bahwa sebagian besar database (termasuk tampaknya MS SQL Server) memiliki tingkat isolasi default "READ COMMITTED", yang mencegah pembacaan yang kotor dan membuat penguncian yang optimis sama akuratnya dengan pesimistis.
Antinome
Eric Brower mengatakan bahwa bankir, tidak seperti yang lain, lebih suka operasi kotor. Guru Anda tampaknya benar-benar kehabisan troli.
Little Alien
1
Eric Brewer adalah guru yang memberikan teorema CAP mengatakan tentang konsistensi dalam perbankan . Ini bertentangan dengan apa yang Anda hormati.
Little Alien
50

Selain apa yang sudah dikatakan:

  • Harus dikatakan bahwa optimisticpenguncian cenderung meningkatkan konkurensi dengan mengorbankan prediktabilitas.
  • Pessimisticmengunci cenderung mengurangi konkurensi, tetapi lebih dapat diprediksi. Anda membayar uang Anda, dll ...
skaffman
sumber
3
Saya tidak melihat bagaimana prediktabilitas (namun Anda mendefinisikannya) ditingkatkan dengan penguncian pesimistis - jika Anda maksudkan 'transaksi dapat diselesaikan setelah kunci diambil' Anda benar, tetapi sampai transaksi memiliki semua kunci yang diperlukan, mungkin menghadapi penundaan untuk mendapatkan kunci yang tersisa, dan pada kenyataannya mungkin dibatalkan karena DB deadlock detection + resolution logic. Aplikasi menggunakan penguncian pesimistis dapat memiliki waktu eksekusi yang sangat tidak terduga - contoh klasiknya adalah seseorang mengunci catatan X lalu pergi makan siang, lalu pengguna mengunci catatan X dan Y, lalu Y dan Z lainnya, dan seterusnya hingga sebagian besar pengguna diblokir. ..
RichVel
40

Saat menangani konflik, Anda memiliki dua opsi:

  • Anda dapat mencoba menghindari konflik, dan itulah yang dilakukan Penguncian Pesimis.
  • Atau, Anda dapat membiarkan konflik terjadi, tetapi Anda perlu mendeteksinya saat melakukan transaksi Anda, dan itulah yang dilakukan Penguncian Optimis.

Sekarang, mari kita pertimbangkan anomali Pembaruan Hilang berikut :

Pembaruan yang Hilang

Anomali Pembaruan yang Hilang dapat terjadi di tingkat isolasi Komitmen Baca .

Dalam diagram di atas kita dapat melihat bahwa Alice yakin dia dapat menarik 40 darinya accounttetapi tidak menyadari bahwa Bob baru saja mengubah saldo akun, dan sekarang hanya ada 20 yang tersisa di akun ini.

Mengunci Pesimistis

Penguncian pesimistis mencapai sasaran ini dengan mengambil kunci yang dibagikan atau dibaca di akun sehingga Bob tidak dapat mengubah akun.

Pembaruan Pesimistis Hilang Penguncian

Dalam diagram di atas, baik Alice dan Bob akan mendapatkan kunci baca di accountbaris tabel yang telah dibaca oleh kedua pengguna. Database memperoleh kunci ini pada SQL Server saat menggunakan Baca berulang atau Serializable.

Karena baik Alice dan Bob telah membaca accountdengan nilai PK 1, tidak satu pun dari mereka dapat mengubahnya sampai satu pengguna melepaskan kunci baca. Ini karena operasi penulisan memerlukan akuisisi kunci tulis / eksklusif, dan kunci bersama / baca mencegah kunci tulis / eksklusif.

Hanya setelah Alice melakukan transaksi dan kunci baca dirilis di accountbaris, Bob UPDATEakan melanjutkan dan menerapkan perubahan. Sampai Alice melepaskan kunci baca, UPDATE Bob memblokir.

Untuk detail lebih lanjut tentang bagaimana kerangka kerja akses data menggunakan dukungan penguncian pesimistis database yang mendasarinya, lihat artikel ini .

Penguncian Optimis

Penguncian yang Optimis memungkinkan terjadinya konflik tetapi mendeteksinya setelah menerapkan UPDATE Alice karena versinya telah berubah.

Transaksi tingkat aplikasi

Kali ini, kami memiliki versionkolom tambahan . The versionkolom bertambah setiap kali UPDATE atau DELETE dijalankan, dan juga digunakan dalam klausa WHERE dari UPDATE dan pernyataan DELETE. Agar ini berfungsi, kita perlu mengeluarkan SELECT dan membaca saat ini versionsebelum menjalankan UPDATE atau DELETE, karena jika tidak, kita tidak akan tahu nilai versi apa yang diteruskan ke klausa WHERE atau kenaikan.

Untuk detail lebih lanjut tentang bagaimana kerangka kerja akses data menerapkan penguncian optimis, lihat artikel ini .

Transaksi tingkat aplikasi

Sistem basis data relasional telah muncul di akhir tahun 80-an awal 80-an ketika seorang klien, biasanya, terhubung ke mainframe melalui terminal. Itu sebabnya kami masih melihat sistem basis data mendefinisikan istilah seperti pengaturan SESI.

Saat ini, melalui Internet, kami tidak lagi menjalankan membaca dan menulis dalam konteks transaksi basis data yang sama, dan ACID tidak lagi memadai.

Misalnya, pertimbangkan use case berikut:

masukkan deskripsi gambar di sini

Tanpa penguncian yang optimis, Lost Update ini tidak mungkin tertangkap bahkan jika transaksi basis data yang digunakan Serializable. Ini karena membaca dan menulis dieksekusi dalam permintaan HTTP yang terpisah, karenanya pada transaksi basis data yang berbeda.

Jadi, penguncian yang optimis dapat membantu Anda mencegah Pembaruan yang Hilang bahkan ketika menggunakan transaksi tingkat aplikasi yang juga memasukkan waktu berpikir pengguna.

Untuk detail lebih lanjut tentang tingkat aplikasi atau transaksi logis, lihat artikel ini .

Kesimpulan

Penguncian optimis adalah teknik yang sangat berguna, dan berfungsi dengan baik bahkan ketika menggunakan tingkat isolasi yang kurang ketat, seperti Read Committed, atau ketika membaca dan menulis dieksekusi dalam transaksi basis data berikutnya.

Kelemahan dari penguncian optimis adalah bahwa kemunduran akan dipicu oleh kerangka kerja akses data setelah menangkap OptimisticLockException, karena itu kehilangan semua pekerjaan yang telah kami lakukan sebelumnya oleh transaksi yang sedang berjalan.

Semakin banyak pertikaian, semakin banyak konflik, dan semakin besar peluang untuk membatalkan transaksi. Kembalikan dapat mahal untuk sistem database karena perlu mengembalikan semua perubahan yang tertunda saat ini yang mungkin melibatkan baris tabel dan catatan indeks.

Karena alasan ini, penguncian pesimistis mungkin cocok untuk saat konflik sering terjadi, karena hal ini mengurangi peluang untuk memutar kembali transaksi.

Vlad Mihalcea
sumber
Untuk skenario apa yang akan Anda sarankan untuk memilih OptimisticLocking dan PessimisticLocking? Apakah ini tergantung pada seberapa sering OptimisticLockException terjadi?
Stimpson Cat
1
Itu tergantung pada use case. Terkadang, penguncian optimis adalah satu-satunya solusi (misalnya, transaksi multi-permintaan). Di lain waktu, penguncian pesimis adalah satu-satunya solusi (mis., Kunci penasehat PostgreSQL ). Terkadang, Anda harus menggabungkannya, seperti halnya dengan PESSIMISTIC_FORCE_INCREMENT.
Vlad Mihalcea
22

Saya akan memikirkan satu lagi kasus ketika penguncian pesimistis akan menjadi pilihan yang lebih baik.

Untuk penguncian yang optimis setiap peserta dalam modifikasi data harus setuju dalam menggunakan penguncian semacam ini. Tetapi jika seseorang memodifikasi data tanpa memperhatikan kolom versi, ini akan merusak seluruh gagasan penguncian optimis.

Nikolay
sumber
Orang-orang yang berusaha menggunakan penguncian yang optimis dan pesimistis juga dapat saling menginjak kaki, sehingga bisa dikatakan. Bayangkan sebuah skenario di mana sesi optimis membaca catatan dan sedang melakukan perhitungan sementara sesi pesimis memperbarui catatan, kemudian sesi optimis kembali dan memperbarui catatan yang sama tanpa memperhatikan perubahan yang dibuat. Pilih ... untuk pembaruan hanya berfungsi jika setiap sesi menggunakan sintaks yang sama.
Hari
Penjelasan Bagus, Berikan Anda suara dari saya
Dulaj Kulathunga
15

Pada dasarnya ada dua jawaban paling populer. Yang pertama pada dasarnya mengatakan

Optimistis membutuhkan arsitektur tiga tingkat di mana Anda tidak perlu menjaga koneksi ke database untuk sesi Anda, sedangkan Pesimis Mengunci adalah ketika Anda mengunci catatan untuk penggunaan eksklusif hingga Anda selesai menggunakannya. Ini memiliki integritas yang jauh lebih baik daripada penguncian optimis yang Anda butuhkan baik koneksi langsung ke database.

Jawaban lain adalah

optimis (versi) lebih cepat karena tidak ada penguncian tetapi penguncian (pesimistis) berkinerja lebih baik ketika pertengkaran tinggi dan lebih baik untuk mencegah pekerjaan daripada membuangnya dan memulai lagi.

atau

Penguncian yang optimis bekerja paling baik ketika Anda memiliki tabrakan yang langka

Seperti yang ada di halaman ini.

Saya membuat jawaban saya untuk menjelaskan bagaimana "menjaga koneksi" terkait dengan "tabrakan rendah".

Untuk memahami strategi mana yang terbaik untuk Anda, jangan pikirkan tentang Transaksi Per Detik yang dimiliki DB Anda tetapi durasi satu transaksi. Biasanya, Anda membuka transaksi, operasi kinerja dan menutup transaksi. Ini adalah transaksi singkat dan klasik yang ada dalam pikiran ANSI dan tidak masalah untuk mengunci. Tetapi, bagaimana Anda menerapkan sistem reservasi tiket di mana banyak klien memesan kamar / kursi yang sama secara bersamaan?

Anda menelusuri penawaran, mengisi formulir dengan banyak opsi yang tersedia dan harga saat ini. Dibutuhkan banyak waktu dan opsi menjadi usang, semua harga tidak valid di antara Anda mulai mengisi formulir dan tekan tombol "Saya setuju" karena tidak ada kunci pada data yang telah Anda akses dan orang lain, yang lebih gesit, telah tertarik mengubah semua harga dan Anda harus memulai kembali dengan harga baru.

Anda bisa mengunci semua opsi saat membacanya. Ini adalah skenario pesimistis. Anda tahu mengapa itu menyebalkan. Sistem Anda dapat dihancurkan oleh satu badut yang baru saja memulai reservasi dan mulai merokok. Tidak ada yang bisa memesan apa pun sebelum dia selesai. Arus kas Anda turun ke nol. Itu sebabnya, pemesanan optimis digunakan dalam kenyataan. Mereka yang terlalu lama harus memulai kembali reservasi mereka dengan harga yang lebih tinggi.

Dalam pendekatan optimis ini Anda harus mencatat semua data yang Anda baca (seperti dalam Repeat Read yang saya baca ) dan sampai pada titik komit dengan versi data Anda (saya ingin membeli saham pada harga yang Anda tampilkan dalam kutipan ini, bukan harga saat ini ). Pada titik ini, transaksi ANSI dibuat, yang mengunci DB, memeriksa apakah tidak ada yang berubah dan melakukan / membatalkan operasi Anda. IMO, ini adalah emulasi efektif dari MVCC , yang juga terkait dengan Optimistic CC dan juga mengasumsikan bahwa transaksi Anda dimulai kembali jika dibatalkan, yaitu Anda akan membuat reservasi baru. Transaksi di sini melibatkan keputusan pengguna manusia.

Saya jauh dari memahami bagaimana mengimplementasikan MVCC secara manual, tetapi saya pikir transaksi jangka panjang dengan opsi restart adalah kunci untuk memahami subjek. Koreksi saya jika saya salah di mana saja. Jawaban saya termotivasi oleh bab Alex Kuznecov ini .

Alien kecil
sumber
12

Dalam kebanyakan kasus, penguncian optimis lebih efisien dan menawarkan kinerja yang lebih tinggi. Saat memilih antara penguncian pesimis dan optimis, pertimbangkan hal berikut:

  • Penguncian pesimis berguna jika ada banyak pembaruan dan peluang yang relatif tinggi dari pengguna yang mencoba memperbarui data pada saat yang sama. Misalnya, jika setiap operasi dapat memperbarui sejumlah besar catatan pada satu waktu (bank mungkin menambahkan pendapatan bunga ke setiap akun pada akhir setiap bulan), dan dua aplikasi menjalankan operasi tersebut pada saat yang sama, mereka akan mengalami konflik .

  • Penguncian pesimistis juga lebih tepat dalam aplikasi yang berisi tabel kecil yang sering diperbarui. Dalam kasus yang disebut hotspot ini, konflik sangat mungkin terjadi sehingga upaya penguncian yang sia-sia akan sia-sia dalam mengembalikan transaksi yang saling bertentangan.

  • Penguncian optimis berguna jika kemungkinan konflik sangat rendah - ada banyak catatan tetapi relatif sedikit pengguna, atau sangat sedikit pembaruan dan sebagian besar operasi tipe-baca.

Koenigsegg
sumber
3

Satu kasus penggunaan untuk penguncian optimis adalah membuat aplikasi Anda menggunakan database untuk memungkinkan salah satu utas / host Anda 'mengklaim' suatu tugas. Ini adalah teknik yang berguna bagi saya secara teratur.

Contoh terbaik yang dapat saya pikirkan adalah untuk antrian tugas yang diimplementasikan menggunakan database, dengan beberapa utas mengklaim tugas secara bersamaan. Jika tugas memiliki status 'Tersedia', 'Diklaim', 'Selesai', permintaan db dapat mengatakan sesuatu seperti "Set status = 'Diklaim' di mana status = 'Tersedia'. Jika beberapa utas mencoba mengubah status dengan cara ini, semua kecuali utas pertama akan gagal karena data kotor.

Perhatikan bahwa ini adalah use case yang hanya melibatkan penguncian optimis. Jadi sebagai alternatif untuk mengatakan "Penguncian optimis digunakan ketika Anda tidak mengharapkan banyak tabrakan", itu juga dapat digunakan di mana Anda mengharapkan tabrakan tetapi ingin tepat satu transaksi berhasil.

Charlie Camp
sumber
3

Banyak hal baik telah dikatakan di atas tentang penguncian optimis dan pesimis. Satu poin penting untuk dipertimbangkan adalah sebagai berikut:

Saat menggunakan penguncian yang optimis, kita perlu berhati-hati terhadap kenyataan bahwa bagaimana aplikasi akan pulih dari kegagalan ini.

Khususnya dalam arsitektur yang didorong pesan asinkron, ini dapat menyebabkan pemrosesan pesan yang tidak sesuai atau pembaruan yang hilang.

Skenario kegagalan perlu dipikirkan.

Abhishek Shinde
sumber