7 điểm bởi GN⁺ 2026-01-07 | 8 bình luận | Chia sẻ qua WhatsApp
  • SQLite là một engine cơ sở dữ liệu gọn nhẹ được triển khai bằng ngôn ngữ C từ năm 2000 và không có kế hoạch viết lại bằng ngôn ngữ khác
  • C được đánh giá là ngôn ngữ phù hợp nhất cho SQLite về hiệu năng, khả năng tương thích, tối thiểu phụ thuộc, và tính ổn định
  • Các ngôn ngữ hướng đối tượng (C++, Java, v.v.) có ràng buộc lớn khi gọi giữa các ngôn ngữ, còn cách tiếp cận thủ tục đôi khi lại đơn giản và nhanh hơn
  • Các “ngôn ngữ an toàn” như Rust hay Go vẫn chưa đủ trưởng thành và không phù hợp với chiến lược chất lượng của SQLite (ví dụ: kiểm thử 100% nhánh, khôi phục OOM)
  • Khả năng chuyển sang Rust trong tương lai vẫn để ngỏ, nhưng cần đáp ứng nhiều điều kiện như độ trưởng thành, khả năng tương thích, hiệu năng, và hỗ trợ công cụ

1. Vì sao C là lựa chọn tốt nhất

  • SQLite lần đầu được triển khai bằng C chuẩn ngay từ đầu vào ngày 29 tháng 5 năm 2000, và đến nay vẫn chưa có kế hoạch chuyển sang ngôn ngữ khác
  • Các lý do khiến C phù hợp với việc triển khai SQLite là hiệu năng, khả năng tương thích, ít phụ thuộc, và tính ổn định

1.1 Hiệu năng

  • SQLite là thư viện cấp thấp được sử dụng với cường độ cao, nên tốc độ là yếu tố bắt buộc
    • Ví dụ, hiệu năng đã được chứng minh trong các tài liệu “Internal Versus External BLOBs” và “35% Faster Than The Filesystem”
  • C được gọi là “ngôn ngữ assembly có tính di động”, vì vừa cho phép kiểm soát gần với phần cứng vừa giữ được tính khả chuyển giữa các nền tảng
  • Các ngôn ngữ khác có thể tuyên bố “nhanh bằng C”, nhưng không có ngôn ngữ nào tuyên bố nhanh hơn C

1.2 Khả năng tương thích

  • Gần như mọi hệ thống đều cung cấp khả năng gọi thư viện được viết bằng C
  • Ví dụ, Android có thể gọi SQLite từ ứng dụng Java thông qua adapter
  • Nếu SQLite được viết bằng Java, thì các ứng dụng iPhone dựa trên Objective-C hoặc Swift đã không thể sử dụng nó

1.3 Tối thiểu phụ thuộc

  • Thư viện viết bằng C có phụ thuộc runtime rất ít
  • Ở cấu hình tối thiểu, SQLite chỉ cần các hàm sau của thư viện C chuẩn
    • memcmp(), memcpy(), memmove(), memset(), strcmp(), strlen(), strncmp()
  • Ngay cả ở bản build đầy đủ, cũng chỉ dùng thêm malloc(), free() và mức vào/ra tệp cơ bản
  • Trong khi đó, các ngôn ngữ hiện đại thường đòi hỏi runtime cỡ nhiều MB và hàng nghìn interface

1.4 Tính ổn định

  • C là một ngôn ngữ lâu đời và ít thay đổi, cung cấp hành vi rõ ràng và có thể dự đoán được
  • Khi phát triển một engine cơ sở dữ liệu nhỏ, nhanh và đáng tin cậy như SQLite, việc đặc tả ngôn ngữ không thay đổi thường xuyên là rất quan trọng

2. Vì sao không được viết bằng ngôn ngữ hướng đối tượng

  • Một số nhà phát triển cho rằng chỉ có thể triển khai hệ thống phức tạp bằng ngôn ngữ hướng đối tượng, nhưng SQLite không như vậy

  • Thư viện viết bằng C++ hoặc Java thường chỉ dùng được trong các ứng dụng viết bằng cùng ngôn ngữ đó

    • Trong khi thư viện C có thể được gọi từ gần như mọi ngôn ngữ
  • Hướng đối tượng là một mẫu thiết kế, không phải bản thân ngôn ngữ, và vẫn có thể triển khai cấu trúc hướng đối tượng trong C

  • Hướng đối tượng không phải lúc nào cũng là lựa chọn tốt nhất; đôi khi mã thủ tục đơn giản hơn và có lợi hơn về bảo trì lẫn hiệu năng

  • Ở giai đoạn đầu phát triển SQLite (đầu những năm 2000), Java còn non trẻ, còn C++ thì gặp vấn đề tương thích nghiêm trọng giữa các compiler

    • Khi đó C rõ ràng là lựa chọn tốt hơn, và đến nay lợi ích của việc viết lại vẫn gần như không có

3. Vì sao không được viết bằng “ngôn ngữ an toàn”

  • Gần đây, các “ngôn ngữ an toàn” như Rust và Go thu hút nhiều chú ý, nhưng SQLite vẫn được duy trì bằng C
  1. Trong 10 năm đầu của SQLite, không tồn tại ngôn ngữ an toàn nào
    • Có thể viết lại bằng Go hoặc Rust, nhưng sẽ có rủi ro phát sinh lỗi mới và suy giảm tốc độ
  2. Ngôn ngữ an toàn chèn thêm các nhánh (branch) như kiểm tra biên mảng
    • Với mã đúng, các nhánh đó sẽ không bao giờ chạy, nên không thể kiểm thử 100% nhánh
  3. Hầu hết các ngôn ngữ an toàn sẽ dừng chương trình khi hết bộ nhớ (OOM)
    • SQLite được thiết kế để khôi phục bình thường ngay cả khi OOM, nên điều này xung đột với cách vận hành đó
  4. Các ngôn ngữ an toàn hiện có đều mới và đang thay đổi nhanh
    • SQLite ưu tiên những ngôn ngữ lâu đời và ổn định

4. Khả năng chuyển sang Rust

  • SQLite có thể được viết lại bằng Rust, nhưng gần như không thể chuyển sang Go
    • Lý do: Go không thích assert()
  • Các điều kiện tiên quyết để chuyển sang Rust
    1. Rust phải trưởng thành hơn và chậm lại về tốc độ thay đổi để trở thành “một ngôn ngữ lâu đời và ổn định”
    2. Rust phải có khả năng tạo ra thư viện phổ dụng có thể được gọi từ mọi ngôn ngữ
    3. Rust phải tạo được object code chạy được cả trên thiết bị nhúng không có hệ điều hành
    4. Rust phải có hệ công cụ hỗ trợ kiểm thử độ bao phủ nhánh 100%
    5. Rust phải cung cấp cơ chế khôi phục OOM
    6. Rust phải chứng minh được việc triển khai không bị mất hiệu năng so với mức C
  • Các nhà phát triển cho rằng Rust đã đáp ứng được các điều kiện trên có thể liên hệ trực tiếp với nhóm SQLite để thảo luận

5. Kết luận

  • SQLite là một engine cơ sở dữ liệu nhỏ, nhanh và đáng tin cậy, và các đặc tính của ngôn ngữ C phù hợp với mục tiêu đó
  • Việc chuyển sang ngôn ngữ hướng đối tượng hoặc ngôn ngữ an toàn không đem lại lợi ích thực tế về khả năng tương thích, hiệu năng hay quản lý chất lượng
  • Sự đơn giản và ổn định của C là nền tảng cho khả năng bảo trì dài hạn và độ tin cậy của SQLite

8 bình luận

 
ndrgrd 2026-01-10

Dù sao thì đây cũng là dự án không nhận PR mà... họ cứ dùng thứ họ muốn dùng thôi

 
skrevolve 2026-01-09

Nếu ở trong bối cảnh cần sự gọn nhẹ thì không có ngôn ngữ nào thay thế được C, C++ hay Rust. Chỉ là không có nhiều lập trình viên thực sự đồng cảm với việc phát triển mà phải lo ngại tràn số hoặc bị khai thác ở mức bit trên struct hoặc map.

 
[Bình luận này đã bị ẩn.]
 
aqqnucs 2026-01-08

Tiêu đề giật gân quá. Nếu đọc bài gốc thì sẽ thấy đây là bài viết nói về lý do vì sao C là ngôn ngữ phù hợp nhất để phát triển SQLite. Mong mọi người bớt giận.

 
aqqnucs 2026-01-08

Không, thậm chí chính bài viết này cũng được viết từ 7 năm trước rồi sao? Có vẻ như sau đó có bổ sung thêm nội dung nên được cập nhật một phần vào năm 2025... 🤦

 
wahihi 2026-01-08

Điều quan trọng là trong nhiều tình huống phát triển khác nhau, phải biết đưa ra phán đoán để dùng ngôn ngữ phù hợp; việc đặt một tiêu đề như vậy, như thể có một ngôn ngữ nào đó lúc nào cũng tốt hơn, thì trình độ tư duy đúng là chỉ ngang học hết cấp hai...

 
m00nny 2026-01-08

Ưu điểm lớn nhất của C, theo tôi, là nó chạm trực tiếp vào bản chất rằng “máy tính là một chuỗi bit”. Triết lý đơn giản của C và việc reinterpret cast mạnh tay tạo nên sức hút ở chỗ người dùng gần như luôn có thể biết nó sẽ được biên dịch thành loại mã máy nào. Không phải vì là C nên có thể được gọi từ mọi ngôn ngữ, mà là vì ABI mới là thứ có thể được gọi; còn trong C, đơn giản là có thể dự đoán được (hoặc phải dự đoán được) đầu vào và đầu ra là chuỗi bit như thế nào. Tôi cũng luôn nghĩ rằng khi bàn về tính khả thi của việc triển khai, điều quan trọng là phải phân biệt xem điều đó là bất khả thi trên máy Turing, hay chỉ là bất khả thi trong ngôn ngữ hoặc framework mà ta đang dùng hiện tại.

 
GN⁺ 2026-01-07
Ý kiến trên Hacker News
  • Tôi không nghĩ cần phải biện minh vì sao không phải mọi dự án hay mọi lập trình viên đều dùng Rust hoặc Zig
    Trên Hacker News và các nền tảng khác, có xu hướng quảng bá các ngôn ngữ này quá mức
    Nếu đã đạt được kết quả đủ tốt với C và người dùng cũng hài lòng, thì người ngoài không có lý do gì để bàn ra tán vào

    • Việc các ngôn ngữ mới được chú ý là điều đương nhiên
      Những người quan tâm đến tiến bộ công nghệ khám phá tiềm năng của ngôn ngữ mới là một diễn biến tự nhiên
      Tuy vậy, người ngoài có quyền nêu ý kiến, nhưng dự án không có nghĩa vụ phải nghe
    • Nhìn vào triết lý thiết kế của Rust và các trường hợp lỗi Rust gần đây trong nhân Linux, Rust không phải là lời giải hoàn hảo
      Rust làm giảm mức độ lộ ra của lỗi, nhưng những loại lỗi tương tự vẫn tồn tại
      Lập trình viên C có xu hướng phản ứng nhạy hơn với race condition, còn Rust có nguy cơ khiến người ta quá tin vào các chú thích “an toàn”
      Ngoài ra trong Rust, việc sửa đổi không hề đơn giản nên gánh nặng refactor có thể lớn hơn
      Cuối cùng, Rust là một ngôn ngữ thú vị nhưng không phải vạn năng, và không nên bị áp đặt
    • Dạo này ngược lại, sự hoài nghi với OOP đang lớn dần
      Những ngôn ngữ như Rust hay Zig có chủ đích rời xa các pattern hướng đối tượng truyền thống
      OOP từng hấp dẫn như một khung khái niệm mang lại “giác ngộ”, nhưng trên thực tế thường làm tăng độ phức tạp và gây hại cho tính mô-đun
    • Nếu Rust tốt hơn trên mọi mặt và giúp giảm bug thì việc mọi người ca ngợi nó cũng không có gì lạ
      Giống như việc dùng máy khoan điện thay vì khoan tay là điều hiển nhiên, nếu có công cụ tốt hơn thì dùng nó là tự nhiên
    • Gần đây chính phủ Mỹ đã khuyến nghị ngừng dùng các ngôn ngữ không an toàn về bộ nhớ (như C)
      Nhưng các công cụ và hoạt động đào tạo để viết mã C an toàn cũng cần phát triển đủ mạnh
  • Tôi là một Rustacean khá nghiêm túc, nhưng không nghĩ việc viết lại mọi dự án bằng Rust là hợp lý
    Nếu chuyển một dự án C đã được kiểm chứng kỹ sang Rust thì trong ngắn hạn thậm chí khả năng bug tăng lên còn cao
    Tuy vậy, một số nơi đang thử thách mình với việc viết lại bằng Rust, ví dụ như Limbo: dự án viết lại hoàn toàn SQLite bằng Rust

    • Limbo thú vị, nhưng ràng buộc không hỗ trợ truy cập đa tiến trình là rất lớn
      Một trong những ưu điểm chính của SQLite là có thể được nhiều tiến trình truy cập đồng thời, nên nếu thiếu điều này thì phạm vi ứng dụng sẽ hẹp đi
    • Các lập trình viên Rust không nhất thiết phải chờ SQLite phê duyệt
      Cứ tự tạo một phiên bản mới và thử nghiệm xem có thành công hay không là được
    • Cá nhân tôi thấy thay vì port SQLite, sẽ hợp lý hơn nếu tạo một embedded DB mới bằng Rust
    • Tôi sẽ tiếp tục theo dõi xem Limbo phát triển thế nào
  • Tôi từng có kinh nghiệm migrate RediSearch sang Rust
    Lý do là vì gần đây có nhiều lỗ hổng CVE
    Nếu SQLite không có vấn đề như vậy thì lý do để chuyển sang Rust là khá yếu
    Có lẽ phải cần đến vài chục năm nữa mới hiểu được đầy đủ điểm mạnh và giới hạn của Rust
    Đặc biệt, hiệu quả của Rust trong ứng dụng GUI vẫn còn chưa rõ ràng

    • Sự ổn định và “nhàm chán” của C là kết quả của hàng chục năm thử và sai
      Rust có lẽ phải đến khoảng năm 2040 mới đạt được mức độ đáng tin cậy tương tự
    • Với những hệ thống như SQLite, các ngôn ngữ như Ada/SPARK có thể còn phù hợp hơn
  • Như Linus đã nhắc đến, Rust cần có cơ chế phục hồi OOM (Out of Memory)
    Có thể xem thêm tại liên kết thảo luận LKML

    • Tuy vậy, bản thân các tính năng ngôn ngữ của Rust về cơ bản tập trung vào cấp phát trên stack, nên không trực tiếp gọi malloc
      Trong mã embedded hoặc mã kernel, thậm chí có thể tắt hoàn toàn tính năng cấp phát
      Tức là Rust vốn đã cung cấp toàn quyền kiểm soát bộ nhớ
    • (Ngoài lề) Cũng có chia sẻ đoạn mã cải thiện CSS của trang đó
    • Nhận xét của Linus là đúng, nhưng phía của ông ấy cũng cần dọn dẹp các vấn đề của mình
  • Khẳng định “không có ngôn ngữ đa dụng nào nhanh hơn C” là một so sánh phiến diện vì bỏ qua thời gian của lập trình viên
    Thay vì mất 5 giờ để làm ra một chương trình chạy 4 giây bằng C, trong thực tế có thể hợp lý hơn nếu dùng ngôn ngữ khác để làm trong 5 phút ra chương trình chạy 5 giây

    • Nhưng với phần mềm như SQLite, nơi thời gian CPU của người dùng áp đảo, hiệu quả của C quan trọng hơn nhiều
      Càng nhiều người dùng, khác biệt tốc độ dù rất nhỏ cũng càng tích lũy thành giá trị lớn
    • Cuối cùng, nếu coi trọng thời gian của người dùng, thì tối ưu hiệu năng bằng C vẫn rất có ý nghĩa
  • Rust còn lâu mới trở thành một ngôn ngữ “nhàm chán nhưng ổn định”
    C được quản lý bởi một ủy ban bảo thủ và giữ tương thích rất nghiêm ngặt, còn Rust thì để giải quyết vấn đề mà ưu tiên đổi mới hơn tương thích

    • Rust thỉnh thoảng phá vỡ tính tương thích ở cấp ngôn ngữ, nhưng hệ thống công cụ thì ổn định
      Mã từ các phiên bản cũ vẫn có thể tiếp tục build bằng compiler mới
    • Rust chọn cách tự động xử lý mã cũ bằng compiler cũ để giảm gánh nặng legacy
      Tôi nghĩ cách này tốt hơn kiểu cứ phải tiếp tục mang vác các tính năng cũ như C++
    • Tính bảo thủ của C không phải là điều “kỳ quặc”, mà là biểu tượng của sự ổn định
    • C ban đầu do một người có quan điểm rất mạnh thiết kế nên có định hướng rõ ràng
      Ngược lại, những ngôn ngữ do ủy ban thiết kế như C++ hay Common Lisp đã trở nên phức tạp hơn
      Rust cũng có quy mô lớn nên cần thận trọng khi dùng cho hệ thống embedded hoặc hệ thống cốt lõi
    • Có vẻ rồi Rust cũng sẽ đến lúc bước vào giai đoạn ổn định
  • Tôi đồng cảm với thái độ “đừng cố sửa thứ vốn đang chạy tốt”
    Lịch sử phát triển ngôn ngữ có vẻ như là quá trình lặp đi lặp lại giữa việc giải quyết vấn đề và tạo ra độ phức tạp mới

    • Mozilla tạo ra Rust vì các vấn đề của C++, nhưng Rust không đơn thuần là vật thay thế cho C++
      C là ví dụ tiêu biểu cho triết lý “Worse is Better”, và đã thành công suốt hàng chục năm nhờ sự đơn giản
      Ngược lại, Rust theo đuổi “Right Thing™”
      Ngày nay, gánh nặng phải tự triển khai mọi thứ đã giảm đi trong phần lớn môi trường, nên giờ đây nó có thể là lựa chọn tốt hơn
      Nhưng không cần phải cố chuyển những dự án đã thành công sang đó
      Nếu là dự án mới thì rất có thể Rust là lựa chọn tốt hơn
  • Sự đơn giản và ổn định của C là ưu điểm đang bị đánh giá thấp
    Tôi nghĩ thay vì tiếp tục thay đổi chính ngôn ngữ, sẽ tốt hơn nếu trau chuốt thư viện chuẩn hoặc hệ sinh thái

    • Tuy vậy, C vẫn còn nhiều UB (undefined behavior) nên vẫn cần cẩn trọng
      Không chỉ sự đơn giản mà bảo đảm hành vi mang tính xác định cũng rất quan trọng
    • Tôi thích những ngôn ngữ đơn giản, thanh lịch và ổn định như Clojure
    • Ngay cả khi thêm tính năng mới cho C, phần lớn đó cũng là các cải tiến thực dụng, ít gây tranh cãi
      Ví dụ tôi thích các tính năng như designated initializer, compound literal, alignas, memset_explicit
  • Cá nhân tôi vẫn cho rằng C là tốt nhất
    Rust có nhiều ý tưởng hay, nhưng cũng là một ngôn ngữ có nhược điểm rất rõ
    Hiện vẫn còn bầu không khí khiến việc thảo luận lạnh lùng về những vấn đề của Rust trở nên khó khăn

    • Nếu chỉ ra cụ thể nhược điểm của Rust là gì thì cuộc thảo luận sẽ hiệu quả hơn
      Ví dụ có thể là độ dốc học tập hay độ phức tạp của đóng gói
    • Tuyên bố “Rust là một ngôn ngữ tệ hại” thì cần có căn cứ cụ thể
  • Câu nói “mọi hệ thống đều có thể gọi thư viện C” giờ không còn đúng nữa
    Rust và Zig cũng đáp ứng được yêu cầu này
    Tuy nhiên, thư viện chuẩn của Rust thường panic thay vì phục hồi khi OOM, và tài liệu cũng còn thiếu

    • Rust và Zig phải dùng tường minh extern "C" hoặc export thì mới tương thích ABI của C
      Nếu không thì ABI không được định nghĩa, nên ngược lại còn có thể kém ổn định hơn cả C++
      Vấn đề này có thể càng lớn hơn, đặc biệt trong các bản phân phối Linux phát hành Rust crate