3 điểm bởi GN⁺ 2023-12-20 | 1 bình luận | Chia sẻ qua WhatsApp
  • Mức cô lập mặc định Repeatable Read của MySQL 8.0.34 cho thấy các vi phạm nhất quán giao dịch không khớp với kỳ vọng ANSI SQL và PL-2.99 của Adya, ngay cả trên một nút đơn hoạt động bình thường
  • Kết hợp trình kiểm tra list-append của Elle, targeted workload và LazyFS để kiểm chứng MySQL 8.0.34, MariaDB 10.11.3, cụm sao chép binlog và AWS RDS MySQL Multi-AZ DB Cluster
  • Tương tự kết quả Hermitage năm 2014 của Kleppmann, các hiện tượng G2-item, G-single và lost update đã được tái hiện; đồng thời còn quan sát thấy vi phạm nhất quán nội bộ, non-repeatable read và Monotonic Atomic View
  • Trên một MySQL đơn, Read Uncommitted, Read Committed và Serializable có vẻ lần lượt phù hợp với PL-1, PL-2, PL-3, nhưng cụm AWS RDS MySQL vẫn xuất hiện G2-item và G-single ngay cả ở Serializable
  • Nếu cần Repeatable Read ở mức ANSI hoặc PL-2.99 thì khó có thể chỉ tin vào MySQL Repeatable Read; cần dùng Serializable hoặc khóa tường minh như SELECT... FOR UPDATE

Đối tượng và phạm vi đánh giá

  • MySQL là một cơ sở dữ liệu quan hệ được sử dụng rộng rãi, và trong phân tích này, “MySQL” có nghĩa là MySQL dùng InnoDB, storage engine mặc định
  • Trọng tâm là MySQL máy chủ đơn, nhưng cũng đề cập đến cụm với một primary ghi đơn và các secondary chỉ đọc dùng sao chép binlog
  • Các đối tượng được kiểm thử gồm:
    • MySQL 8.0.34
    • MariaDB 10.11.3
    • Debian Bookworm
    • profile “Multi-AZ DB Cluster” của AWS RDS Cluster
  • Công việc được thực hiện độc lập, không nhận thù lao và tuân theo Jepsen ethics policy

Mức cô lập SQL và tiêu chuẩn của Repeatable Read

  • ANSI SQL định nghĩa Read Uncommitted, Read Committed, Repeatable Read và Serializable theo khả năng xảy ra của P1 dirty read, P2 non-repeatable read và P3 phantom
  • Năm 1995, Berenson và cộng sự trong A Critique of ANSI SQL Isolation Levels đã phê phán tính mơ hồ và thiếu sót của định nghĩa ANSI
    • P1, P2, P3 có chỗ để diễn giải khác nhau
    • Thiếu các hiện tượng quan trọng như P0 dirty write
    • P3 chỉ cấm insert ảnh hưởng đến predicate, không xử lý update hay delete
  • Bài báo năm 1999 của Atul Adya định nghĩa các mức cô lập độc lập với triển khai dựa trên đồ thị phụ thuộc giữa các giao dịch
    • PL-1 cấm G0 write cycle
    • PL-2 cấm G0 và G1
    • PL-2.99 cấm G0, G1, G2-item và tương ứng với Repeatable Read
    • PL-3 cấm G0, G1, G2 và tương ứng với Serializable
  • Jepsen thường dùng khuôn khổ của Adya để phân tích log giao dịch và xác định anomaly

Xung đột giữa tài liệu MySQL và Repeatable Read

  • Tài liệu MySQL nói rằng InnoDB cung cấp đầy đủ bốn mức cô lập của chuẩn SQL:1992
  • Mức cô lập mặc định Repeatable Read được mô tả là các consistent read trong cùng một giao dịch sẽ đọc snapshot được thiết lập ở lần đọc đầu tiên
  • Tài liệu về consistent read cũng nói rằng cơ sở dữ liệu được nhìn thấy theo mốc thời gian của lần đọc đầu tiên
  • Tuy nhiên, ghi chú trong chính tài liệu đó cho biết snapshot áp dụng với SELECT nhưng không nhất thiết áp dụng với câu lệnh DML, và DELETE hoặc UPDATE có thể tác động đến các row mà giao dịch khác đã commit
  • Ghi chú này mâu thuẫn với ANSI SQL và cả reference manual của MySQL, nơi SELECT cũng được xem là DML, đồng thời tạo ra sự mơ hồ rằng trong Repeatable Read, ghi có thể ảnh hưởng đến các row mà trước đó không thể đọc thấy

Thiết kế kiểm thử

  • Bộ test cho MySQL được viết dựa trên Jepsen testing library 0.3.4
  • Client dùng adapter JDBC mysql-connector-j
  • Kiểm thử bao gồm fault injection như process pause, crash, network partition và mất các ghi đĩa chưa fsync
  • Tuy vậy, gần như mọi phát hiện trong phân tích này đều xảy ra trên một nút MySQL đơn đang ở trạng thái bình thường
  • Workload list-append của Elle

    • Workload cốt lõi dùng list-append checker của Elle
    • Elle suy luận các phụ thuộc write-write, write-read, read-write giữa các giao dịch và dùng cycle trong đồ thị phụ thuộc để chứng minh vi phạm một mức cô lập cụ thể
    • Workload list-append thực hiện các giao dịch ngẫu nhiên gồm read và append trên nhiều list được nhận diện bằng primary key
    • List được mã hóa trong một trường text chứa các giá trị phân tách bằng dấu phẩy, và append được xử lý bằng SQL CONCAT
    • Nhờ các cải tiến gần đây, Elle phát hiện tốt hơn:
      • suy luận phụ thuộc ww/rw với các phần tử append chưa được đọc
      • phát hiện tường minh P4 lost update
      • tìm cycle phức tạp bao gồm real-time edge và process edge
  • Targeted workload

    • Workload non-repeatable read nhắm vào một row trong bảng people
    • Một nhóm giao dịch chỉ update name, còn nhóm khác đọc name, update gender, rồi đọc lại name
    • Nếu name thay đổi giữa hai lần đọc thì đó là vi phạm Repeatable Read
    • Workload Monotonic Atomic View dùng value của hai row
    • Writer tăng value của row 0 rồi tăng row 1
    • Reader đọc row 0, update noop của row 1, rồi đọc row 1 và row 0
    • Nếu đã thấy một phần hiệu ứng của một giao dịch thì phải thấy toàn bộ hiệu ứng của giao dịch đó
  • LazyFS

    • LazyFS là một filesystem FUSE mô phỏng mất các ghi chưa fsync
    • Cách kiểm thử là giết process MySQL, bỏ cache của LazyFS rồi khởi động lại MySQL
    • Đây là báo cáo Jepsen công khai đầu tiên có dùng LazyFS

Các anomaly được phát hiện trong MySQL Repeatable Read

  • G2-item

    • Repeatable Read PL-2.99 của Adya cấm G2-item, tức cycle phụ thuộc write-write, write-read, read-write không chứa predicate
    • MySQL Repeatable Read lặp đi lặp lại cho phép G2-item ngay cả trên một nút đơn bình thường
    • Hành vi mà Kleppmann báo cáo trong Hermitage năm 2014 vẫn tiếp diễn trong MySQL 8.0.34
    • Một bài test ví dụ cho thấy 214 cycle trong 40 giây
    • Hành vi này bị cấm trong Repeatable Read theo PL-2.99, nhưng theo định nghĩa P2 của ANSI SQL thì vẫn còn khoảng trống diễn giải vì P2 chỉ nói tới việc đọc cùng một row hai lần
  • G-single và read skew

    • MySQL Repeatable Read cũng xuất hiện G-single
    • G-single là cycle gồm các cạnh write-write, write-read, read-write nhưng các cạnh read-write không kề nhau
    • Read skew mà Kleppmann báo cáo năm 2014 cũng được xác nhận lại trên MySQL 8.0.34
    • Trong bài test append 60 giây, ở mức khoảng 140 giao dịch/giây đã xuất hiện 244 trường hợp G-single và 305 trường hợp G2-item
    • Vì bài test append không dùng thao tác predicate, tất cả đều được phân loại là vi phạm Repeatable Read
  • Lost update

    • P4 lost update là trường hợp đặc biệt của G-single, khi hai giao dịch đọc cùng một version của cùng một key rồi cả hai cùng update
    • Snapshot Isolation và Repeatable Read PL-2.99 đều cấm lost update
    • MySQL Repeatable Read lặp đi lặp lại cho phép lost update ngay cả trên một nút đơn bình thường
    • Trong một bài test, trong số 9.048 giao dịch thành công, checker mới tìm thấy 446 giao dịch liên quan đến 198 trường hợp lost update
    • Trong số này chỉ có 47 trường hợp lộ ra dưới dạng cycle
    • Mẫu đọc rồi ghi giá trị không an toàn trong MySQL Repeatable Read
    • Với mẫu ORM phổ biến là đọc đối tượng, sửa trong bộ nhớ rồi lưu lại, các thay đổi đã commit có thể âm thầm biến mất
    • Người dùng phải tự dùng khóa tường minh
  • Non-repeatable read và vi phạm nhất quán nội bộ

    • MySQL Repeatable Read cho thấy vi phạm nhất quán nội bộ ngay cả trên một nút đơn bình thường
    • Trong cùng lần chạy test đó, 126 trên 9.048 giao dịch commit có lỗi nhất quán nội bộ
    • Ở ví dụ đầu, một giao dịch đọc key là nil, append thêm một giá trị, rồi khi đọc lại cùng key thì quan sát thấy đã có thêm ba giá trị khác
    • Ở ví dụ khác, khi đọc key 1096 là [1 2 3], append 7, rồi đọc lại thì thấy [1 2 3 4 5 6 7]
    • Trong targeted workload, bên trong một giao dịch Repeatable Read, name được đọc là "pebble", sau đó gender được update thành "femme", nhưng khi đọc lại cùng name thì kết quả là "moss"
    • Hành vi này trái với định nghĩa non-repeatable read của ANSI SQL và mô tả “snapshot được thiết lập ở lần đọc đầu tiên” trong tài liệu MySQL
  • Vi phạm Monotonic Atomic View

    • Monotonic Atomic View là thuộc tính yêu cầu rằng nếu một giao dịch đã thấy bất kỳ hiệu ứng nào của một giao dịch khác thì nó phải thấy mọi hiệu ứng của giao dịch đó
    • MySQL Repeatable Read lặp đi lặp lại vi phạm điều này ngay cả trên một nút đơn bình thường
    • Trong workload, writer tăng row 0 rồi tăng row 1
    • Reader thấy giá trị cũ 0 ở row 0, sau đó thấy phần tăng 1 của writer ở row 1, rồi khi đọc lại row 0 vẫn thấy 0
    • Đây là đọc không đơn điệu: thấy hiệu ứng của row 1 nhưng không thấy hiệu ứng của row 0, không phù hợp với hành vi snapshot thông thường

Các anomaly trong AWS RDS MySQL Serializable

  • Cụm AWS RDS MySQL lặp đi lặp lại vi phạm Serializability ngay cả ở mức cô lập “Serializable”
  • Trong cụm RDS MySQL với profile production được khuyến nghị mặc định, bài test append xuất hiện anomaly G2-item và G-single
  • Anomaly được quan sát có dạng một giao dịch bỏ lỡ phụ thuộc đi trước của một giao dịch khác dù đã thấy hiệu ứng của giao dịch đó
  • Anomaly này vừa được phân loại là G-single vừa là G2-item, và vi phạm Snapshot Isolation, Repeatable Read lẫn Serializability
  • Cấu hình liên quan đến replica_preserve_commit_order vẫn là yếu tố bị nghi ngờ
    • Từ MySQL 8.0.27 trở lên, mặc định là replica_preserve_commit_order=ON
    • Tham số mặc định của RDS vẫn chọn cấu hình tương ứng với replica_preserve_commit_order=OFF
    • Trong RDS parameter group, thiết lập này dùng tên cũ là slave_preserve_commit_order
    • Khi áp dụng thiết lập này trên cụm test cục bộ, cũng quan sát thấy các trường hợp G-single và G2-item tương tự

Những phần có vẻ hoạt động đúng và kết quả LazyFS

  • Read Uncommitted, Read Committed và Serializable của MySQL 8.0.34 có vẻ lần lượt thỏa mãn PL-1, PL-2 và PL-3
  • Kết quả này được quan sát cả trên nút đơn lẫn trên cụm nhỏ có read-only replica dùng sao chép binlog
  • Kết quả vẫn giữ nguyên dưới các tình huống process pause, crash và network partition
  • Fault injection bằng LazyFS không tìm thấy vấn đề nào trong cấu hình mặc định của MySQL
  • Với mặc định innodb_flush_log_at_trx_commit=1, không thấy mất giao dịch đã commit sau process crash và mất dữ liệu chưa fsync
  • Khi đổi thành innodb_flush_log_at_trx_commit=0, MySQL chỉ fsync khoảng vài giây một lần và quan sát thấy mất dữ liệu

Bản chất thực tế của MySQL Repeatable Read

  • MySQL Repeatable Read không thỏa mãn Repeatable Read PL-2.99
    • Xuất hiện G2-item và write skew
  • Nó cũng không thỏa mãn Snapshot Isolation
    • Xuất hiện G-single, read skew và lost update
  • Nó cũng không thỏa mãn cursor stability
    • Có lost update
  • Read Atomic, Causal Consistency, Consistent View, Prefix Consistency và Parallel Snapshot Isolation cũng bị loại trừ
    • Đã quan sát thấy vi phạm nhất quán nội bộ
  • MySQL Repeatable Read có vẻ mạnh hơn Read Committed một chút
    • Không quan sát thấy G0 dirty write, G1a aborted read, G1b intermediate read hay G1c cyclic information flow
    • Tính lặp lại của một số lần đọc mạnh hơn đặc tính của Read Committed
  • Tuy nhiên, vẫn chưa rõ chính xác MySQL Repeatable Read thuộc consistency model nào, và cũng không có định nghĩa chính thức về các thuộc tính của nó

Sự lệch nhau giữa tài liệu và cách hiểu của cộng đồng

  • Trong cộng đồng MySQL, hành vi của Repeatable Read vẫn chưa được hiểu đầy đủ
  • Nhiều bài viết tin rằng MySQL Repeatable Read ngăn lost update, nhưng cũng có bài cho rằng không ngăn được và khuyên dùng khóa tường minh
  • Nhiều tài liệu trên Internet nói rằng MySQL Repeatable Read thực sự là repeatable, nhưng các bài test của Jepsen cho thấy những trường hợp không như vậy
  • Tài liệu của MySQL và MariaDB cũng mô tả rằng Repeatable Read sẽ đọc cùng một snapshot trong cùng một giao dịch
  • Một câu trong tài liệu về consistent read của MySQL ám chỉ hành vi trái ngược với mô tả này, nhưng nội dung đó bị chôn sâu trong tài liệu

Khuyến nghị

  • Nếu MySQL giữ nguyên hành vi hiện tại, họ nên ghi rõ “Repeatable Read” thực sự cung cấp consistency model nào
  • Lựa chọn khác là coi hành vi hiện tại là bug và sửa nó
  • Jepsen cho biết nếu MySQL và các vendor khác cam kết cung cấp Repeatable Read theo PL-2.99 thì họ hoan nghênh
  • Người dùng cần PL-2.99 hoặc ANSI Repeatable Read nên thận trọng với MySQL Repeatable Read
  • Các lựa chọn thực tế gồm:
    • Dùng mức cô lập Serializable của MySQL
    • Tăng cường đọc ở READ COMMITTED bằng kỹ thuật khóa như SELECT ... FOR UPDATE

Khuyến nghị cho người dùng RDS

  • Cụm AWS RDS MySQL xuất hiện read skew và G2-item ở mức “Serializable”
  • Người dùng phụ thuộc vào Serializability nên đặt slave_preserve_commit_order thành ON trong RDS parameter group
  • Có đề xuất rằng AWS nên đổi giá trị mặc định hoặc mô tả rõ các vi phạm Serializability được cho phép trong tài liệu known limitations của RDS MySQL

Công việc tiếp theo và lời kêu gọi chuẩn hóa

  • MySQL binlog replication có vẻ mong manh
    • Trong các bài test Jepsen cục bộ đã quan sát thấy nhiều tình huống replication dừng lại
    • Replication của AWS RDS MySQL có thể hỏng hoàn toàn chỉ sau vài phút test, và đã có trường hợp CREATE DATABASE thành công trên primary nhưng không xuất hiện trên secondary suốt 1 giờ mà không tự phục hồi
  • Báo cáo không khảo sát việc nâng secondary thành primary hoặc các topology sao chép như ring hay star
  • Nghiên cứu về bài test predicate tổng quát hơn để đánh giá predicate safety đang được tiến hành
  • Định nghĩa mức cô lập của ANSI SQL vẫn không thay đổi dù đã 28 năm từ khi Berenson và cộng sự chỉ ra tính mơ hồ, thiếu sót và đã trải qua 7 lần sửa đổi ANSI·ISO
  • Cần một định nghĩa mức cô lập hình thức và có tính di động hơn để ISO/IEC 9075-2 xử lý rõ ràng các hiện tượng như anomaly nội bộ, lost update và dirty write

1 bình luận

 
GN⁺ 2023-12-20
Ý kiến trên Hacker News
  • Tôi từ lâu đã cho rằng repeatable read là một ý tưởng tồi, kể cả khi cách triển khai của nó có hoàn hảo đến đâu
    Ngay cả khi nó hoạt động đúng bên trong cơ sở dữ liệu, với các truy vấn phức tạp thì việc suy luận vẫn quá khó
    Tôi cho rằng chỉ có hai mức cô lập hợp lý là read committedserializable
    Hoặc đi thẳng đến serializable để không gặp điều bất ngờ nào, hoặc dùng read committed với quy tắc rõ ràng rằng nếu cần một view nhất quán bên trong transaction thì phải khóa hàng trước khi đọc
    read committed gần với code đa luồng và quản lý bộ nhớ thông thường hơn nên kỹ sư dễ có trực giác hơn, còn serializable thì nghiêm ngặt đến mức khó tạo ra lỗi bất ngờ
    Phần ở giữa là vùng vô chủ, và bất cứ thứ gì kém nhất quán hơn read committed thì khó còn có thể xem là một cơ sở dữ liệu đúng nghĩa

    • Tôi không nghĩ mọi người suy luận tốt về read committed
      Khi ứng dụng lớn dần, việc hiểu hết mọi trường hợp dữ liệu được truy cập và khóa được giữ ở đâu trở nên cực kỳ khó
      Với transaction đọc/ghi, chỉ serializable mới là mô hình cô lập hợp lý; còn với transaction chỉ đọc, snapshot isolation xử lý snapshot cơ sở dữ liệu tại một thời điểm cụ thể là một mô hình tốt
      Các chế độ Spanner cung cấp trên thực tế cũng chỉ là hai loại này: https://cloud.google.com/spanner/docs/transactions
    • read uncommitted có thể chấp nhận được cho thống kê tổng hợp, nhưng nếu chỉ vậy thì tốt hơn nên đẩy dữ liệu sang ClickHouse
    • Truy vấn snapshot chỉ đọc rất hữu ích trong các hệ thống thực tế
    • Nếu repeatable read thực sự hoạt động đúng thì sẽ không cần phải khóa hàng
  • Có một bài thuyết trình tại FOSSDEM 2024 so sánh mức cô lập và MVCC của các cơ sở dữ liệu SQL
    Bao gồm Oracle, MySQL, SQL Server, PostgreSQL và YugabyteDB
    https://fosdem.org/2024/schedule/event/fosdem-2024-3600-isol...

    • Người trình bày là một developer advocate đang làm ở YugabyteDB, nên tôi tò mò không biết điều này liên hệ với công việc của Kyle như thế nào
  • Tôi tò mò append(a) được ánh xạ như thế nào sang phép toán SQL thực tế trên bảng đã cho
    Có phải dùng trường TEXT như một danh sách không?
    Trong chế độ MySQL repeatable read, tôi từng thấy một SELECT đơn trên một hàng đơn lẻ trả về kết quả bất khả thi
    Nó có dạng SELECT min(value), max(value) FROM table WHERE id = 1;, trong đó id là khóa chính, nhưng minmax lại ra các giá trị khác nhau

  • Bài viết rất hay và tôi thích việc nó đề cập đến AWS RDS, nhưng tôi tò mò liệu có tập trung vào AWS Aurora MySQL hay không
    Nói cho ai chưa biết, AWS đã tạo ra một nền tảng cơ sở dữ liệu tương thích giao thức nhưng chỉ giả làm MySQL hoặc PostgreSQL
    Sẽ rất thú vị nếu xem Aurora MySQL có những “đặc điểm” giống như RDS hay MariaDB hay không

    • Aurora là một DB engine hoàn toàn khác nên các vấn đề đồng thời cũng khác, vì vậy có lẽ nó không được đề cập ở đây
      Dù vậy, đây vẫn là một đối tượng rất thú vị, và vì Aurora là cơ sở dữ liệu mới hơn nhiều nên tôi có linh cảm nó vẫn còn những vấn đề tinh vi chưa được phát hiện mà MySQL cũ hơn có thể đã lộ ra rồi
    • Tôi dùng MySQL Aurora khá nhiều, và với nhu cầu của chúng tôi thì lưu lượng rất cao nhưng mẫu truy vấn đơn giản nên không thấy khác biệt lớn lắm
      Tuy vậy có một điểm gây khó chịu khá lớn
      Các kỹ sư của Plaid đã viết một bài tổng hợp khá tốt về sự khác biệt: https://plaid.com/blog/exploring-performance-differences-bet...
      Với tôi, khác biệt lớn nhất là cụm Aurora dùng shared storage nên mô hình cô lập hơi khác một chút
      read committed chỉ khả dụng nếu cấu hình tham số cho toàn bộ cụm, còn read uncommitted thì theo tôi thấy là không thể
  • Bài viết rất thú vị
    Nó cho thấy rõ có thể xây được bao nhiêu “hệ thống thực sự chạy được” trên một nền tảng vẫn bộc lộ rất nhiều bất thường về tính nhất quán

    • Phần lớn các hệ thống thực chất là hỏng, chỉ vận hành được nhờ con người liên tục vá víu và hiệu chỉnh thủ công
  • Việc chỉ đụng vào khoảng 5 phút mà sao chép RDS đã dừng, lại còn không có cảnh báo health check thất bại, thì khá đáng lo

    • Chi tiết rất quan trọng và gần như không thể chẩn đoán vấn đề chỉ bằng screencast, nhưng theo kinh nghiệm của tôi thì AWS nhìn chung cung cấp CloudWatch Metrics khá hào phóng
      Chỉ là họ thường đẩy gánh nặng cho người dùng phải lục qua hơn 150 chỉ số và đọc tài liệu để tìm ra thứ quan trọng
      Ngoài ra, <https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_...> có nói là có một ô trong bảng trên console hiển thị trạng thái sao chép, nhưng trên console thì người dùng thường phải tự bật cột đó lên, nên khá tệ
      AWS đang dựa khá nhiều vào cái gọi là “mô hình trách nhiệm chung”
    • Tôi có thể khẳng định là không nên tin bất kỳ AWS health check nào như cảnh báo đầu tiên cho tình huống bị sập
      Tất cả phải tự làm trực tiếp từ bên trong host hoặc container
      Hỗ trợ của AWS/Rackspace chỉ nói rằng “những gì chạy bên trong dịch vụ AWS thì chúng tôi không quản, đó là vấn đề của khách hàng”
  • Tôi thích đoạn nói rằng năm 2022 Jepsen đã nhờ INESC TEC của Đại học Porto phát triển LazyFS
    Một filesystem FUSE mô phỏng việc mất các lần ghi chưa được fsync, đúng là ví dụ tuyệt vời về việc đẩy trình độ kỹ thuật tiến lên phía trước

  • SELECT ... FOR UPDATE có vẻ như là câu trả lời cho những vấn đề này
    Chẳng phải nếu khóa hàng cần cập nhật thì đột nhiên mọi thứ sẽ hoạt động đúng như quảng cáo sao?

    • Nói chung, thao tác khóa hàng có xu hướng “cố định” sự tồn tại của giá trị bất kể repeatable read
      Nếu muốn cập nhật một bản ghi dựa trên dữ liệu của bản ghi khác, thì cần đọc có khóa bản ghi kia và có lẽ cả bản ghi sẽ cập nhật nữa
      Nếu cập nhật một bản ghi dựa trên bản ghi khác bằng một truy vấn SQL duy nhất thì MySQL dù sao cũng sẽ khóa cả hai
      Nếu phải cập nhật thứ gì đó dựa trên nhiều đối tượng, thì theo kinh nghiệm của tôi deadlock rất dễ xảy ra
      Thay vào đó, tốt hơn là khóa một thứ như bản ghi dùng để khóa, rồi thực hiện repeatable read trên dữ liệu mong muốn và cập nhật
      Thời điểm của repeatable read không được xác định cho đến khi thực hiện một lần đọc nhất quán
      SELECT ... FOR UPDATE không phải là đọc nhất quán, nên nó hoạt động tốt trong tình huống đồng thời mà không cần khóa hàng chục hay hàng trăm hàng bằng một lệnh cập nhật SQL thông thường
    • Đúng, nếu bạn chấp nhận hiệu năng bị phá hủy hoàn toàn
  • Theo kinh nghiệm của tôi, phần lớn lập trình viên vốn dĩ không hề cân nhắc mức cô lập mà cứ dùng mặc định
    Khi gặp race condition thì chỉ kiểu “ơ lạ nhỉ” rồi bỏ qua

    • Tôi muốn phản bác, nhưng thời kỳ đầu thành công của MongoDB lại là bằng chứng quá rõ cho điều đó
    • Đó là lý do tôi nói mức cô lập mặc định phải là serializable
      [1] https://news.ycombinator.com/item?id=38696421
    • Các vấn đề về cô lập quá khó để suy luận, nên hầu hết mọi thứ thấp hơn tính nhất quán serializable cuối cùng sẽ cản trở bạn theo nhiều cách
      Vì thế, phần lớn lập trình viên tốt hơn là không nên tự mình bận tâm về mức cô lập, và tôi cho rằng MySQL cùng một số cơ sở dữ liệu khác cung cấp quá ít mức đảm bảo cho lập trình viên trung bình
    • Theo kinh nghiệm của tôi, gần như chẳng có lập trình viên nào thậm chí còn nghĩ đến tính nhất quán