3 poin oleh GN⁺ 2023-12-20 | 1 komentar | Bagikan ke WhatsApp
  • Repeatable Read, level isolasi bawaan MySQL 8.0.34, menunjukkan pelanggaran konsistensi transaksi yang tidak sesuai dengan ekspektasi ANSI SQL dan PL-2.99 dari Adya, bahkan pada satu node sehat
  • Dengan menggabungkan list-append checker Elle, targeted workload, dan LazyFS, pengujian memverifikasi MySQL 8.0.34, MariaDB 10.11.3, klaster replikasi binlog, serta AWS RDS MySQL Multi-AZ DB Cluster
  • Seperti hasil Hermitage Kleppmann pada 2014, G2-item, G-single, dan lost update berhasil direproduksi; pelanggaran konsistensi internal, non-repeatable read, serta pelanggaran Monotonic Atomic View juga diamati
  • Read Uncommitted, Read Committed, dan Serializable pada MySQL tunggal tampak masing-masing sesuai dengan PL-1, PL-2, dan PL-3, tetapi klaster AWS RDS MySQL menunjukkan G2-item dan G-single bahkan pada Serializable
  • Jika membutuhkan Repeatable Read pada level ANSI atau PL-2.99, sulit mengandalkan MySQL Repeatable Read saja; diperlukan Serializable atau locking eksplisit seperti SELECT... FOR UPDATE

Target dan cakupan evaluasi

  • MySQL adalah basis data relasional yang banyak digunakan, dan dalam analisis ini “MySQL” berarti MySQL yang menggunakan InnoDB sebagai storage engine bawaan
  • Fokusnya adalah MySQL server tunggal, tetapi juga mencakup klaster dengan primary penulis tunggal dan secondary read-only yang menggunakan replikasi binlog
  • Target pengujian adalah sebagai berikut
    • MySQL 8.0.34
    • MariaDB 10.11.3
    • Debian Bookworm
    • Profil “Multi-AZ DB Cluster” pada AWS RDS Cluster
  • Pekerjaan dilakukan secara independen tanpa kompensasi, dan mengikuti kebijakan etika Jepsen

Level isolasi SQL dan kriteria Repeatable Read

  • ANSI SQL mendefinisikan Read Uncommitted, Read Committed, Repeatable Read, dan Serializable berdasarkan kemungkinan P1 dirty read, P2 non-repeatable read, dan P3 phantom
  • Pada 1995, Berenson dkk. dalam A Critique of ANSI SQL Isolation Levels mengkritik ambiguitas dan ketidaklengkapan definisi ANSI
    • P1, P2, dan P3 dapat ditafsirkan dengan berbagai cara
    • Fenomena penting seperti P0 dirty write tidak tercakup
    • P3 hanya melarang insert yang memengaruhi predicate, tetapi tidak membahas update atau delete
  • Makalah Atul Adya tahun 1999 mendefinisikan level isolasi yang independen dari implementasi berdasarkan graf dependensi antartransaksi
    • PL-1 melarang G0 write cycle
    • PL-2 melarang G0 dan G1
    • PL-2.99 melarang G0, G1, dan G2-item, serta berpadanan dengan Repeatable Read
    • PL-3 melarang G0, G1, dan G2, serta berpadanan dengan Serializable
  • Jepsen umumnya menggunakan formalitas Adya untuk menilai riwayat transaksi dan anomali

Konflik antara dokumentasi MySQL dan Repeatable Read

  • Dokumentasi MySQL menjelaskan bahwa InnoDB menyediakan keempat level isolasi standar SQL:1992
  • Repeatable Read, level isolasi bawaan, dijelaskan bahwa consistent read dalam transaksi yang sama membaca snapshot yang ditetapkan pada pembacaan pertama
  • Dokumentasi consistent read juga menjelaskan bahwa database dilihat berdasarkan timepoint pada pembacaan pertama
  • Namun catatan dalam dokumen yang sama mengatakan bahwa snapshot berlaku untuk SELECT, tetapi tidak selalu berlaku untuk pernyataan DML, dan DELETE atau UPDATE dapat menyentuh row yang sudah di-commit oleh transaksi lain
  • Catatan ini bertentangan dengan ANSI SQL dan manual referensi MySQL yang juga menganggap SELECT sebagai DML, serta menimbulkan kebingungan bahwa pada Repeatable Read, operasi tulis dapat memengaruhi row yang sebelumnya tidak dapat dibaca

Desain pengujian

  • Test suite untuk MySQL ditulis berdasarkan Jepsen testing library 0.3.4
  • Klien menggunakan adaptor JDBC mysql-connector-j
  • Pengujian mencakup fault injection seperti process pause, crash, network partition, dan hilangnya penulisan disk yang belum di-fsync
  • Namun hampir semua temuan dalam analisis ini terjadi pada satu node MySQL dalam kondisi sehat
  • Elle list-append workload

    • Workload utama menggunakan list-append checker dari Elle
    • Elle menyimpulkan dependensi write-write, write-read, dan read-write antartransaksi, lalu membuktikan pelanggaran level isolasi tertentu melalui cycle pada graf dependensi
    • List-append workload menjalankan transaksi acak yang terdiri dari read dan append terhadap beberapa list yang diidentifikasi dengan primary key
    • List dienkode sebagai field text berisi nilai yang dipisahkan koma, dan append diproses dengan SQL CONCAT
    • Dengan perbaikan terbaru, Elle lebih baik dalam mendeteksi hal-hal berikut
      • Inferensi dependensi ww/rw terhadap append element yang belum terbaca
      • Deteksi eksplisit P4 lost update
      • Pencarian cycle kompleks yang mencakup real-time edge dan process edge
  • Targeted workload

    • Non-repeatable read workload menargetkan satu row pada tabel people
    • Satu rangkaian transaksi hanya meng-update name, sedangkan rangkaian lain membaca name, meng-update gender, lalu membaca name lagi
    • Jika name berubah di antara dua pembacaan, itu adalah pelanggaran Repeatable Read
    • Monotonic Atomic View workload menggunakan value dari dua row
    • Writer menaikkan value row 0, lalu menaikkan row 1
    • Reader membaca row 0, meng-update noop row 1, lalu membaca row 1 dan row 0
    • Jika sebagian efek dari sebuah transaksi terlihat, semua efeknya juga harus terlihat
  • LazyFS

    • LazyFS adalah filesystem FUSE yang menyimulasikan hilangnya penulisan yang belum di-fsync
    • Pengujian dilakukan dengan mematikan process MySQL, membuang cache LazyFS, lalu memulai ulang MySQL
    • Laporan ini adalah laporan Jepsen publik pertama yang mencakup LazyFS

Anomali yang ditemukan pada MySQL Repeatable Read

  • G2-item

    • PL-2.99 Repeatable Read dari Adya melarang G2-item, yaitu cycle dependensi write-write, write-read, dan read-write yang tidak melibatkan predicate
    • MySQL Repeatable Read berulang kali mengizinkan G2-item, bahkan pada satu node sehat
    • Perilaku yang dilaporkan Kleppmann pada 2014 di Hermitage masih terjadi di MySQL 8.0.34
    • Contoh pengujian menunjukkan 214 cycle selama 40 detik
    • Perilaku ini dilarang dalam PL-2.99 Repeatable Read, tetapi karena definisi P2 ANSI SQL hanya membahas kasus membaca row yang sama dua kali, masih ada ruang interpretasi menurut definisi ANSI
  • G-single dan read skew

    • MySQL Repeatable Read juga menunjukkan G-single
    • G-single adalah cycle yang terdiri dari edge write-write, write-read, dan read-write, tetapi edge read-write tidak saling bersebelahan
    • Read skew yang dilaporkan Kleppmann pada 2014 dikonfirmasi kembali di MySQL 8.0.34
    • Dalam pengujian append 60 detik, pada sekitar 140 transaksi per detik, muncul 244 G-single dan 305 G2-item
    • Karena pengujian append tidak menggunakan operasi predicate, semuanya diklasifikasikan sebagai pelanggaran Repeatable Read
  • Lost update

    • P4 lost update adalah kasus khusus G-single ketika dua transaksi membaca version yang sama dari key yang sama dan keduanya meng-update
    • Snapshot Isolation dan PL-2.99 Repeatable Read melarang lost update
    • MySQL Repeatable Read berulang kali mengizinkan lost update, bahkan pada satu node sehat
    • Dalam satu pengujian, dari 9.048 transaksi sukses, checker baru menemukan 446 transaksi yang terlibat dalam 198 kasus lost update
    • Dari kasus-kasus ini, hanya 47 yang terlihat sebagai cycle
    • Pola membaca nilai lalu menulisnya tidak aman pada MySQL Repeatable Read
    • Dalam pola ORM standar yang membaca objek, memodifikasinya di memori, lalu menyimpannya kembali, perubahan yang sudah di-commit dapat hilang secara diam-diam
    • Pengguna harus menggunakan locking eksplisit sendiri
  • Non-repeatable read dan pelanggaran konsistensi internal

    • MySQL Repeatable Read menunjukkan pelanggaran konsistensi internal, bahkan pada satu node sehat
    • Dalam run pengujian yang sama, 126 dari 9.048 transaksi commit menunjukkan kesalahan konsistensi internal
    • Dalam contoh, sebuah transaksi membaca key sebagai nil, menambahkan satu nilai, lalu saat membaca lagi key yang sama, mengamati tiga nilai lain sudah ditambahkan
    • Dalam contoh lain, key 1096 dibaca sebagai [1 2 3], lalu 7 di-append, dan saat dibaca lagi terlihat [1 2 3 4 5 6 7]
    • Dalam targeted workload, di dalam satu transaksi Repeatable Read, name dibaca sebagai "pebble", gender di-update menjadi "femme", lalu saat name yang sama dibaca lagi, hasilnya "moss"
    • Perilaku seperti ini bertentangan dengan definisi non-repeatable read ANSI SQL dan penjelasan dokumentasi MySQL bahwa snapshot “ditetapkan pada pembacaan pertama”
  • Pelanggaran Monotonic Atomic View

    • Monotonic Atomic View adalah sifat bahwa transaksi yang melihat salah satu efek dari sebuah transaksi harus melihat semua efek transaksi tersebut
    • MySQL Repeatable Read berulang kali melanggarnya, bahkan pada satu node normal
    • Dalam workload, writer menaikkan row 0 lalu menaikkan row 1
    • Reader melihat nilai sebelumnya 0 pada row 0, kemudian melihat kenaikan writer 1 pada row 1, lalu kembali melihat 0 pada row 0
    • Ini adalah pembacaan non-monotonik: efek pada row 1 terlihat, tetapi efek pada row 0 tidak terlihat, sehingga tidak sesuai dengan perilaku snapshot yang umum

Anomali pada AWS RDS MySQL Serializable

  • Klaster AWS RDS MySQL berulang kali melanggar Serializability bahkan pada level isolasi “Serializable”
  • Pada klaster RDS MySQL dengan profil production yang direkomendasikan secara default, pengujian append menunjukkan anomali G2-item dan G-single
  • Anomali yang diamati berbentuk transaksi lain melewatkan dependensi sebelumnya dari suatu transaksi yang efeknya telah dilihat
  • Anomali ini diklasifikasikan sebagai G-single sekaligus G2-item, dan melanggar Snapshot Isolation, Repeatable Read, serta Serializability
  • Pengaturan terkait replica_preserve_commit_order tetap menjadi faktor yang dicurigai
    • MySQL 8.0.27 ke atas menjadikan replica_preserve_commit_order=ON sebagai default
    • Parameter bawaan RDS masih memilih pengaturan yang setara dengan replica_preserve_commit_order=OFF
    • RDS parameter group menggunakan nama lama pengaturan ini, yaitu slave_preserve_commit_order
    • Jika pengaturan ini diterapkan pada klaster pengujian lokal, G-single dan G2-item serupa teramati

Bagian yang tampak normal dan hasil LazyFS

  • Read Uncommitted, Read Committed, dan Serializable pada MySQL 8.0.34 tampak masing-masing memenuhi PL-1, PL-2, dan PL-3
  • Hasil ini diamati baik pada node tunggal maupun pada klaster kecil dengan read-only replica yang menggunakan replikasi binlog
  • Hasil tersebut tetap bertahan pada process pause, crash, dan network partition
  • Fault injection LazyFS tidak menemukan masalah pada konfigurasi bawaan MySQL
  • Dengan nilai default innodb_flush_log_at_trx_commit=1, tidak tampak kehilangan transaksi yang sudah di-commit bahkan setelah process crash dan hilangnya data yang belum di-fsync
  • Jika diubah menjadi innodb_flush_log_at_trx_commit=0, MySQL hanya melakukan fsync sekali setiap beberapa detik, dan kehilangan data teramati

Karakter sebenarnya dari MySQL Repeatable Read

  • MySQL Repeatable Read tidak memenuhi PL-2.99 Repeatable Read
    • Menunjukkan G2-item dan write skew
  • Tidak memenuhi Snapshot Isolation
    • Menunjukkan G-single, read skew, dan lost update
  • Tidak memenuhi cursor stability
    • Lost update terjadi
  • Read Atomic, Causal Consistency, Consistent View, Prefix Consistency, dan Parallel Snapshot Isolation juga dikesampingkan
    • Pelanggaran konsistensi internal diamati
  • MySQL Repeatable Read tampak sedikit lebih kuat daripada Read Committed
    • G0 dirty write, G1a aborted read, G1b intermediate read, dan G1c cyclic information flow tidak diamati
    • Repeatability pada sebagian pembacaan memberikan sifat yang lebih kuat daripada Read Committed
  • Namun tidak jelas secara persis model consistency apa yang diberikan MySQL Repeatable Read, dan tidak ada definisi sifat yang formal

Ketidaksesuaian antara dokumentasi dan pemahaman komunitas

  • Di komunitas MySQL, perilaku Repeatable Read belum dipahami dengan cukup baik
  • Beberapa tulisan meyakini bahwa MySQL Repeatable Read mencegah lost update, tetapi tulisan lain menyatakan bahwa ia tidak mencegahnya dan menyarankan penggunaan locking eksplisit
  • Banyak materi internet mengatakan bahwa MySQL Repeatable Read benar-benar repeatable, tetapi pengujian Jepsen menunjukkan kasus yang tidak demikian
  • Dokumentasi MySQL dan MariaDB juga menjelaskan bahwa Repeatable Read membaca snapshot yang sama dalam transaksi yang sama
  • Satu kalimat dalam dokumentasi consistent read MySQL mengisyaratkan perilaku yang bertentangan dengan penjelasan ini, tetapi konten tersebut tersembunyi di dalam dokumentasi

Rekomendasi

  • Jika MySQL mempertahankan perilaku saat ini, ia harus mendokumentasikan dengan jelas model consistency apa yang sebenarnya diberikan oleh “Repeatable Read”
  • Pilihan lain adalah memperlakukan perilaku saat ini sebagai bug dan memperbaikinya
  • Jepsen menyatakan akan menyambut baik jika MySQL dan vendor lain berkomitmen menyediakan PL-2.99 Repeatable Read
  • Pengguna yang membutuhkan PL-2.99 atau ANSI Repeatable Read harus berhati-hati dengan MySQL Repeatable Read
  • Alternatif praktis adalah sebagai berikut
    • Menggunakan level isolasi Serializable pada MySQL
    • Memperkuat pembacaan dengan teknik locking seperti SELECT ... FOR UPDATE pada READ COMMITTED

Rekomendasi untuk pengguna RDS

  • Klaster AWS RDS MySQL menunjukkan read skew dan G2-item pada “Serializable”
  • Pengguna yang bergantung pada Serializability harus mengatur slave_preserve_commit_order menjadi ON di RDS parameter group
  • Ada usulan agar AWS mengubah default, atau menjelaskan secara eksplisit pelanggaran Serializability yang diperbolehkan dalam dokumentasi known limitations untuk RDS MySQL

Pekerjaan mendatang dan permintaan standardisasi

  • MySQL binlog replication tampak rapuh
    • Dalam pengujian Jepsen lokal, ditemukan beberapa situasi ketika replication berhenti
    • AWS RDS MySQL replication dapat sepenuhnya rusak hanya dengan beberapa menit pengujian, dan kondisi ketika CREATE DATABASE yang sukses di primary tidak muncul di secondary tidak pulih selama 1 jam
  • Promosi secondary menjadi primary maupun topology replikasi seperti ring dan star tidak dieksplorasi
  • Penelitian mengenai predicate test yang lebih umum untuk mengevaluasi predicate safety sedang berlangsung
  • Definisi level isolasi ANSI SQL belum berubah meskipun 28 tahun telah berlalu sejak Berenson dkk. menunjukkan ambiguitas dan ketidaklengkapannya, serta sudah ada 7 revisi ANSI·ISO
  • Dibutuhkan definisi level isolasi yang lebih formal dan portabel agar ISO/IEC 9075-2 dapat menangani secara jelas fenomena seperti internal anomaly, lost update, dan dirty write

1 komentar

 
GN⁺ 2023-12-20
Opini Hacker News
  • Saya sudah lama menganggap repeatable read sebagai ide buruk meskipun implementasinya sempurna
    Sekalipun bekerja dengan benar di dalam database, pada kueri yang kompleks penalarannya terlalu rumit
    Menurut saya hanya ada dua tingkat isolasi yang masuk akal: read committed dan serializable
    Entah sekalian memakai serializable sampai akhir agar tidak ada kejutan, atau memakai read committed yang jelas bahwa jika membutuhkan tampilan yang konsisten di dalam transaksi, baris harus dikunci sebelum dibaca
    read committed lebih dekat dengan kode multithreaded umum dan manajemen memori, sehingga engineer lebih mudah memiliki intuisi; sedangkan serializable begitu ketat sehingga sulit menimbulkan kesalahan tak terduga
    Yang di tengah adalah wilayah tak bertuan, dan apa pun yang kurang konsisten daripada read committed sulit dianggap sebagai database yang layak

    • Saya tidak melihat orang-orang bisa menalar read committed dengan baik
      Semakin besar aplikasi, semakin sulit memahami semua kemungkinan tentang di mana lock diambil dan data diakses
      Untuk transaksi baca/tulis, hanya serializable yang merupakan model isolasi yang waras; untuk transaksi read-only, snapshot isolation, yang menangani snapshot database pada titik waktu tertentu, adalah model yang baik menurut saya
      Mode yang disediakan Spanner pun pada dasarnya hanya dua ini: https://cloud.google.com/spanner/docs/transactions
    • read uncommitted oke untuk statistik agregat, tetapi kalau hanya sejauh itu lebih baik mengalirkan datanya ke ClickHouse
    • Kueri snapshot read-only sangat berguna dalam sistem nyata
    • Jika repeatable read benar-benar bekerja dengan semestinya, seharusnya tidak perlu mengunci baris
  • Di FOSSDEM 2024 ada presentasi yang membandingkan tingkat isolasi dan MVCC pada database SQL
    Mencakup Oracle, MySQL, SQL Server, PostgreSQL, YugabyteDB
    https://fosdem.org/2024/schedule/event/fosdem-2024-3600-isol...

    • Presenternya adalah developer advocate yang bekerja di YugabyteDB, jadi saya penasaran bagaimana ini terhubung dengan pekerjaan Kyle
  • Saya penasaran append(a) dipetakan seperti apa ke operasi SQL nyata pada tabel yang diberikan
    Apakah field TEXT dipakai seperti list?
    Di mode repeatable read MySQL, saya juga pernah melihat satu SELECT yang memilih satu baris mengembalikan hasil yang mustahil
    Bentuknya SELECT min(value), max(value) FROM table WHERE id = 1;, dan id adalah primary key, tetapi min dan max keluar sebagai nilai yang berbeda

  • Artikelnya bagus dan saya senang AWS RDS ikut dibahas, tetapi saya penasaran apakah AWS Aurora MySQL juga menjadi fokus
    Bagi yang belum tahu, AWS membuat platform database yang kompatibel protokol dan berpura-pura sebagai MySQL atau PostgreSQL
    Akan menarik melihat apakah Aurora MySQL memiliki “fitur” yang sama seperti RDS atau MariaDB

    • Aurora adalah engine DB yang sepenuhnya berbeda, jadi isu konkurensinya juga berbeda dan mungkin tidak dibahas di sini
      Meski begitu, itu target yang sangat menarik, dan karena Aurora adalah database yang jauh lebih baru, saya punya firasat ada masalah halus yang belum ditemukan dibandingkan MySQL yang lebih lama
    • Saya cukup banyak memakai MySQL Aurora, dan untuk penggunaan kami, meskipun volumenya sangat tinggi, pola kuerinya sederhana sehingga perbedaan besar tidak terlalu terlihat
      Namun ada satu hal yang sangat menjengkelkan
      Para engineer Plaid menulis artikel yang merangkum perbedaannya dengan baik: https://plaid.com/blog/exploring-performance-differences-bet...
      Perbedaan terbesar bagi saya adalah karena cluster Aurora memakai shared storage, model isolasinya sedikit berbeda
      read committed hanya bisa digunakan dengan menetapkan parameter di seluruh cluster, dan read uncommitted menurut saya tidak mungkin
  • Artikel yang sangat menarik
    Ini menunjukkan dengan baik betapa banyak “sistem yang benar-benar berjalan” bisa dibangun di atas fondasi yang memperlihatkan begitu banyak anomali konsistensi

    • Sebagian besar sistem pada dasarnya rusak, dan berjalan dengan mengakalinya lewat koreksi manusiawi
  • Bagian yang agak mengkhawatirkan adalah ketika disentuh dalam 5 menit, replikasi RDS berhenti, dan tidak ada notifikasi health check yang gagal

    • Detailnya penting dan hampir mustahil memecahkan masalah hanya dari screencast, tetapi dari pengalaman saya AWS umumnya menyediakan CloudWatch Metrics dengan cukup berlimpah
      Namun mereka cenderung melempar beban kepada pengguna untuk menyisir lebih dari 150 metrik dan membaca dokumentasi agar menemukan yang penting
      Selain itu, <https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_...> mengatakan ada sel tabel konsol yang menampilkan status replikasi, tetapi di konsol pengguna sering harus mengaktifkan sendiri tampilan kolom tersebut, dan ini kurang baik
      AWS cukup banyak mengandalkan apa yang mereka sebut “model tanggung jawab bersama”
    • Saya bisa memastikan bahwa AWS health check apa pun tidak boleh dipercaya sebagai notifikasi utama saat terjadi downtime
      Semuanya harus dilakukan sendiri dari dalam host atau container
      Dukungan AWS/Rackspace hanya akan berkata, “apa yang berjalan di dalam layanan AWS tidak kami kelola, jadi itu masalah pelanggan”
  • Saya suka bagian bahwa pada 2022 Jepsen menugaskan INESC TEC Universitas Porto untuk mengembangkan LazyFS
    Sebuah filesystem FUSE yang menyimulasikan hilangnya write yang belum di-fsync; ini contoh bagus yang mendorong tingkat teknis ke depan

  • SELECT ... FOR UPDATE tampak seperti jawaban untuk masalah-masalah ini
    Kalau baris yang akan di-update dikunci, bukankah tiba-tiba semuanya bekerja seperti yang diiklankan?

    • Secara umum, operasi yang mengunci baris cenderung “memakukan” nilai agar tetap ada, terlepas dari repeatable read
      Jika ingin memperbarui suatu record berdasarkan data dari record lain, Anda perlu melakukan locking read pada record lain itu, dan mungkin juga pada record yang akan diperbarui
      Jika memperbarui record berdasarkan record lain dengan satu kueri SQL, MySQL pada akhirnya akan mengunci keduanya
      Jika perlu memperbarui sesuatu berdasarkan banyak target, dari pengalaman saya deadlock sangat mudah terjadi
      Sebagai gantinya, lebih baik mengunci sesuatu seperti record khusus untuk locking, lalu melakukan repeatable read pada data yang diinginkan dan memperbaruinya
      Titik waktu repeatable read belum ditentukan sampai Anda melakukan consistent read
      SELECT ... FOR UPDATE bukan consistent read, jadi ia bekerja baik dalam situasi konkurensi tanpa perlu mengunci puluhan atau ratusan baris dengan update SQL biasa
    • Benar, jika Anda tidak masalah performanya benar-benar hancur
  • Dari pengalaman saya, sebagian besar developer sejak awal tidak mempertimbangkan isolation level dan memakai default apa adanya
    Ketika muncul race condition, mereka hanya berkata “eh, aneh ya” lalu lanjut

    • Saya ingin membantah, tetapi masa-masa awal MongoDB yang sukses membuktikan pernyataan itu dengan baik
    • Karena itulah saya mengatakan isolation level default seharusnya serializable
      [1] https://news.ycombinator.com/item?id=38696421
    • Masalah isolasi terlalu sulit untuk dinalar, sehingga sebagian besar hal di bawah konsistensi serializable pada akhirnya akan menjegal Anda dengan berbagai cara
      Jadi sebagian besar developer sebaiknya tidak perlu memikirkan isolation level sendiri, dan menurut saya MySQL serta beberapa database lain memberikan tingkat jaminan yang terlalu sedikit bagi developer rata-rata
    • Dari pengalaman saya, hampir tidak ada developer yang mempertimbangkan konsistensi itu sendiri