SQLite trong phát triển di động: nó là gì và hoạt động như thế nào

Tác giả: IT Sectr Đã đăng: 2026-03-11 Thời gian đọc: 10 phút

SQLite là một cơ sở dữ liệu quan hệ nhúng hoạt động mà không cần tiến trình máy chủ riêng biệt và lưu trữ toàn bộ cơ sở dữ liệu trong một tệp duy nhất trên thiết bị. Nhờ cấu hình bằng không, kích thước thư viện nhỏ và hỗ trợ SQL đầy đủ, SQLite đã trở thành tiêu chuẩn cho lưu trữ dữ liệu cục bộ trong các ứng dụng di động. Theo SQLite Consortium (2025), DBMS này được sử dụng trên hơn 4 tỷ thiết bị, bao gồm mọi điện thoại thông minh trên iOS và Android.

Những điểm chính

  • SQLite là một DBMS quan hệ nhúng với cấu hình bằng không và lưu trữ dữ liệu trong một tệp duy nhất.
  • Giao dịch ACID đảm bảo tính toàn vẹn dữ liệu ngay cả khi mất điện hoặc ứng dụng bị treo.
  • Kiểu dữ liệu là động: SQLite không yêu cầu chỉ định chặt chẽ kiểu cột khi tạo bảng.
  • Room là thư viện ORM Android giúp đơn giản hóa việc làm việc với SQLite thông qua DAO và chú thích.
  • CoreData có thể sử dụng SQLite làm Persistent Store trên iOS nhưng thêm một lớp quản lý đối tượng.

SQLite là gì?

SQLite là một thư viện ngôn ngữ C triển khai DBMS quan hệ không cần máy chủ chuyên dụng. Nó được nhúng trực tiếp vào ứng dụng, đọc và ghi dữ liệu vào một tệp thông thường trên hệ thống tệp của thiết bị. Kích thước thư viện khoảng 600 KB, khiến SQLite trở thành cơ sở dữ liệu SQL đầy đủ tính năng nhẹ nhất.

SQLite hỗ trợ hầu hết tiêu chuẩn SQL:1999, bao gồm JOIN, truy vấn con, trigger, view, chỉ mục và hàm cửa sổ. Các hạn chế liên quan đến ALTER TABLE (hỗ trợ hạn chế) và RIGHT/FULL OUTER JOIN đầy đủ. Tuy nhiên, đối với ứng dụng di động, chức năng của SQLite đủ dùng trong 99% trường hợp lưu trữ cục bộ.

Theo khảo sát nhà phát triển Stack Overflow (2025), SQLite là cơ sở dữ liệu phổ biến nhất cho các giải pháp nhúng và đứng thứ ba về mức độ phổ biến trong tất cả DBMS sau MySQL và PostgreSQL. Trong phát triển di động, SQLite được sử dụng trong mọi ứng dụng — trực tiếp hoặc thông qua các trình bao bọc.

Các đặc điểm chính của SQLite

Cấu hình bằng không — SQLite không yêu cầu cài đặt, thiết lập quyền, tạo người dùng hay khởi động dịch vụ. Thư viện được liên kết với dự án và cơ sở dữ liệu được tạo bằng cách gọi một hàm duy nhất. Điều này giúp đơn giản hóa triển khai một cách triệt để so với các DBMS client-server yêu cầu cài đặt máy chủ, cấu hình cổng và thiết lập người dùng.

Tệp cơ sở dữ liệu SQLite là một tệp đa nền tảng thông thường có thể được sao chép, phân tích, gửi qua mạng hoặc khôi phục từ bản sao lưu. Định dạng tệp ổn định ở cấp API: các tệp SQLite 3 được tạo năm 2004 vẫn mở được bằng phiên bản thư viện hiện tại, đảm bảo khả năng tương thích dữ liệu lâu dài.

SQLite hoạt động như thế nào: kiến trúc và lưu trữ

Kiến trúc của SQLite bao gồm tám máy ảo: Tokenizer, Parser, Code Generator, VM, B-Tree, Pager, OS Interface và Utilities. Một truy vấn SQL đi qua Tokenizer (chia thành token), Parser (xây dựng AST), Code Generator (chuyển đổi thành bytecode) và được thực thi trên máy ảo, máy này đọc các trang dữ liệu thông qua B-Tree và Pager.

SQLite sử dụng B-Tree để lưu trữ bảng và chỉ mục. Mỗi bảng được lưu trữ dưới dạng một B-Tree riêng biệt, trong đó các nút lá chứa các hàng dữ liệu. Các chỉ mục cũng được lưu trữ dưới dạng B-Tree nhưng với các khóa trong lá. Pager quản lý việc tải các trang (mặc định 4096 byte) từ tệp vào bộ nhớ, cung cấp các giao dịch ACID thông qua nhật ký hoặc WAL.

Các chế độ ghi nhật ký

WAL (Write-Ahead Logging) là chế độ được khuyến nghị cho ứng dụng di động. Các thay đổi trước tiên được ghi vào một tệp WAL riêng biệt, sau đó định kỳ được chuyển vào cơ sở dữ liệu chính. WAL cho phép đọc (dữ liệu cũ) và ghi (qua WAL) đồng thời vào cơ sở dữ liệu, cải thiện hiệu suất của các ứng dụng đa luồng. Nhật ký tiêu chuẩn (rollback journal) chặn đọc trong khi ghi.

Tham sốRollback JournalWAL (Write-Ahead Logging)
Đọc trong khi ghiBị chặnĐược phép (đọc dữ liệu cũ)
Hiệu suất ghiTrung bìnhCao (ghi tuần tự vào WAL)
Tiêu thụ đĩaÍt hơn (chỉ nhật ký rollback)Nhiều hơn (WAL + cơ sở dữ liệu chính)
Khôi phục sự cốRollback đến điểm kiểm tra cuốiKhôi phục từ WAL (không mất dữ liệu)
Khuyến nghịCho kịch bản đơn luồngCho ứng dụng di động thông thường

Việc chuyển đổi giữa các chế độ được thực hiện bằng một truy vấn SQL duy nhất: PRAGMA journal_mode=WAL. Đối với ứng dụng di động có đồng bộ hóa nền và luồng UI đọc dữ liệu đồng thời, WAL cung cấp hiệu suất tốt hơn và không bị khóa giao diện.

SQLite so với các cơ sở dữ liệu khác trong phát triển di động

SQLite không phải là lựa chọn duy nhất cho lưu trữ dữ liệu cục bộ, nhưng là linh hoạt nhất. Realm cung cấp tốc độ truy cập trực tiếp vào đối tượng trong bộ nhớ cao hơn nhưng sử dụng định dạng NoSQL riêng và có kích thước thư viện lớn hơn. Core Data trên iOS là một lớp ORM trên SQLite giúp thêm quản lý đồ thị đối tượng và hoàn tác thao tác.

Đối với hầu hết ứng dụng, SQLite vẫn là lựa chọn tối ưu nhờ hiệu suất có thể dự đoán, không bị khóa nhà cung cấp và độ ổn định đã được kiểm chứng qua thời gian. Realm và Core Data phù hợp trong các dự án có đồ thị đối tượng phức tạp, truy vấn phản ứng hoặc yêu cầu đồng bộ hóa giữa các thiết bị.

Đặc điểmSQLiteRealmCore Data
Loại cơ sở dữ liệuQuan hệ (SQL)NoSQL (dựa trên đối tượng)ORM (trên SQLite)
Kích thước thư viện~600 KB~4 MBTích hợp trong SDK Apple
Hiệu suấtTrung bìnhCao (đối tượng trong bộ nhớ)Trung bình (chi phí ORM)
Nền tảngiOS, Android, Web, DesktopiOS, Android, Node.jsiOS, macOS
Khóa nhà cung cấpKhông có (tiêu chuẩn mở)Trung bình (định dạng độc quyền)Cao (chỉ Apple)

Việc lựa chọn giữa SQLite, Realm và Core Data phụ thuộc vào nền tảng, yêu cầu mô hình đối tượng và chiến lược đồng bộ hóa. Đối với các dự án đa nền tảng (KMP, Flutter), SQLite vẫn là lựa chọn phổ quát duy nhất hoạt động trên tất cả các nền tảng mục tiêu mà không thay đổi mô hình dữ liệu.

SQLite trên Android: Room và SQLiteOpenHelper

Room là một thư viện từ Android Jetpack cung cấp lớp ORM trên SQLite. Room tự động tạo truy vấn SQL từ các giao diện DAO được chú thích, xác thực tính đúng đắn của truy vấn tại thời điểm biên dịch và hỗ trợ di chuyển cơ sở dữ liệu khi lược đồ thay đổi. Room là cách được khuyến nghị để làm việc với SQLite trên Android.

SQLiteOpenHelper là API cấp thấp để quản lý SQLite trực tiếp mà không cần ORM. Lớp này quản lý việc tạo, mở và nâng cấp cơ sở dữ liệu. SQLiteOpenHelper phù hợp cho các dự án có truy vấn SQL đơn giản hoặc khi cần kiểm soát hoàn toàn logic SQL mà không cần sự trừu tượng hóa của Room.

Ví dụ về Entity và DAO cho Room

Một entity trong Room được chú thích bằng @Entity, và DAO bằng @Dao. Room dịch các phương thức được chú thích thành truy vấn SQL: @Insert tạo INSERT, @Query tạo SELECT với SQL được chỉ định. Di chuyển được thêm qua Migration với các phiên bản lược đồ cũ và mới được chỉ định. Room xác thực SQL tại thời điểm biên dịch, loại bỏ lỗi cú pháp trong sản xuất.

kotlin
@Entity
data class User(
    @PrimaryKey val id: Long,
    val name: String,
    @ColumnInfo(name = "created_at")
    val createdAt: Long
)

@Dao
interface UserDao {
    @Query("SELECT * FROM user ORDER BY name ASC")
    suspend fun getAllUsers(): List<User>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertUser(user: User)

    @Query("DELETE FROM user WHERE id = :id")
    suspend fun deleteUser(id: Long)
}

Room tự động tạo ra triển khai UserDao_Impl, chứa các truy vấn SQLite thời gian chạy thông qua RoomDatabase nội bộ. Nhờ coroutine (suspend), các phương thức DAO thực thi bất đồng bộ trên luồng nền mà không chặn UI. Kiểu trả về Flow trong @Query tự động cập nhật kết quả khi bảng thay đổi.

SQLite trên iOS: FMDB và GRDB

FMDB là một trình bao bọc Objective-C trên API C của SQLite, trong lịch sử là thư viện phổ biến đầu tiên cho iOS. Nó cung cấp các đối tượng FMDatabase và FMResultSet để thực thi truy vấn và lấy kết quả. FMDB đơn giản và tối giản, nhưng không hỗ trợ các cấu trúc đặc thù của Swift — optionals, Codable, async/await.

GRDB là một thư viện Swift hiện đại để làm việc với SQLite. Nó cung cấp API an toàn kiểu, hỗ trợ Codable, Combine Publishers, async/await, di chuyển và quan sát thay đổi thời gian thực. GRDB được ưa chuộng cho các dự án Swift mới nhờ tích hợp đầy đủ với Swift Concurrency và khả năng đọc mã tốt hơn.

Ví dụ GRDB trong Swift

GRDB định nghĩa bảng thông qua các lớp Record tuân thủ các giao thức FetchableRecordTableRecord. Các truy vấn được viết bằng Swift với cú pháp an toàn kiểu thay vì SQL thô. GRDB cũng hỗ trợ DatabaseMigrator để quản lý phiên bản lược đồ và di chuyển giữa các phiên bản ứng dụng.

swift
struct User: Codable, FetchableRecord, TableRecord {
    var id: Int64
    var name: String
    var createdAt: Date
}

let dbPool = try DatabasePool(path: dbPath)
var migrator = DatabaseMigrator()
migrator.registerMigration("v1") { db in
    try db.create(table: "user") { t in
        t.autoIncrementedPrimaryKey("id")
        t.column("name", .text).notNull()
        t.column("createdAt", .datetime).notNull()
    }
}

let users = try await dbPool.read { db in
    try User.order(Column("name")).fetchAll(db)
}

DatabasePool sử dụng chế độ WAL của SQLite để đọc đồng thời. Nhiều trình đọc có thể truy cập cơ sở dữ liệu đồng thời trong khi một trình ghi duy nhất cập nhật dữ liệu qua WAL. GRDB tự động quản lý kết nối và giao dịch, cung cấp quyền truy cập cơ sở dữ liệu an toàn luồng từ bất kỳ luồng nào mà không cần đồng bộ hóa thủ công.

Tối ưu hiệu suất SQLite

Chỉ mục là cách hiệu quả nhất để tăng tốc truy vấn SQLite. Một chỉ mục được tạo trên các cột được sử dụng trong mệnh đề WHERE, JOIN và ORDER BY. Đối với bảng có 100000 bản ghi, tìm kiếm trên cột được đánh chỉ mục mất mili giây thay vì giây. Tuy nhiên, chỉ mục làm chậm thao tác INSERT và UPDATE, do đó số lượng của chúng cần được cân bằng với tần suất ghi.

Chèn hàng loạt (batch insert) trong một giao dịch duy nhất giúp tăng tốc tải dữ liệu hàng loạt một cách triệt để. Chèn 1000 bản ghi từng cái một gây ra chi phí khoảng 1 giây. Cùng 1000 bản ghi trong một giao dịch duy nhất mất khoảng 5-10 mili giây. Sự khác biệt được giải thích bởi mỗi INSERT riêng lẻ tạo ra một giao dịch mới với ghi đồng bộ lên đĩa.

PRAGMA hiệu suất

PRAGMA là các lệnh SQLite để cấu hình hành vi thư viện. Các pragma tối ưu hóa chính: PRAGMA synchronous=NORMAL (giảm tần suất fsync), PRAGMA cache_size=-8000 (cấp phát 8 MB bộ nhớ đệm), PRAGMA temp_store=MEMORY (bảng tạm thời trong bộ nhớ). Đối với ứng dụng di động có khối lượng dữ liệu lớn, kết hợp các pragma này giúp tăng tốc truy vấn gấp 2-3 lần.

Một tối ưu hóa quan trọng khác là biên dịch trước các truy vấn SQL (prepared statements). Nếu một truy vấn được thực thi nhiều lần (ví dụ: chèn 10000 hàng), biên dịch SQL một lần và tái sử dụng câu lệnh giúp giảm tải CPU 30-50%. Room và GRDB tự động lưu cache prepared statements, nhưng khi sử dụng trực tiếp API C của SQLite, việc biên dịch phải được thực hiện thủ công.

kotlin
class UserRepository(private val db: RoomDatabase) {

    suspend fun insertBatch(users: List<User>) {
        db.withTransaction {
            users.chunked(500).forEach { batch ->
                batch.forEach { user ->
                    insertUser(user)
                }
            }
        }
    }
}

Chèn hàng loạt với withTransaction đảm bảo tất cả thao tác INSERT được thực thi trong một giao dịch duy nhất. Việc chia thành các lô nhỏ (chunked) ngăn một giao dịch trở nên quá lớn, có thể chặn các luồng khác trong thời gian dài. Đối với đồng bộ hóa nền, kích thước lô nhỏ 500 bản ghi cung cấp sự cân bằng tối ưu giữa tốc độ và khả năng phản hồi của UI.

Câu hỏi thường gặp

Có thể sử dụng SQLite trên nhiều luồng không?

Có, SQLite hỗ trợ truy cập đa luồng ở chế độ WAL. Nhiều luồng có thể đọc dữ liệu đồng thời, nhưng chỉ một luồng có thể ghi. Room và GRDB quản lý đồng bộ hóa tự động. Ở chế độ rollback journal (mặc định), cơ sở dữ liệu bị khóa hoàn toàn trong bất kỳ thao tác ghi nào.

Kích thước cơ sở dữ liệu SQLite tối đa trên thiết bị di động là bao nhiêu?

Giới hạn của SQLite là 281 TB (tối đa lý thuyết). Trong thực tế, kích thước cơ sở dữ liệu bị giới hạn bởi bộ nhớ khả dụng của thiết bị. Đối với ứng dụng di động, kích thước thoải mái lên đến 1-2 GB. Cơ sở dữ liệu lớn hơn 2 GB làm chậm sao lưu, cập nhật qua App Store và tăng tiêu thụ RAM.

Dữ liệu trong SQLite có an toàn không?

SQLite không mã hóa dữ liệu theo mặc định — bất kỳ tiến trình nào có quyền truy cập tệp đều có thể đọc được. Để mã hóa, hãy sử dụng SQLCipher (tiện ích mở rộng với AES-256), Room với EncryptedDatabase (Android) hoặc Encrypted Core Data trên iOS. Mã hóa thêm 5-15% chi phí cho các thao tác đọc và ghi dữ liệu.

Sự khác biệt giữa SQLite và MySQL là gì?

SQLite là một thư viện nhúng không yêu cầu tiến trình máy chủ. MySQL là DBMS client-server với máy chủ riêng biệt, người dùng, quyền truy cập và giao thức mạng. SQLite lưu trữ cơ sở dữ liệu trong một tệp duy nhất; MySQL lưu trữ trong nhiều tệp do máy chủ quản lý. SQLite đơn giản và nhẹ hơn; MySQL mạnh mẽ và có khả năng mở rộng hơn.

Làm thế nào để cập nhật lược đồ SQLite mà không mất dữ liệu?

Để di chuyển SQLite, hãy sử dụng ALTER TABLE (thêm cột) hoặc tạo bảng mới với chuyển dữ liệu và xóa bảng cũ. Room tự động hóa quy trình này thông qua các lớp Migration: chỉ định startVersion, endVersion và truy vấn SQL cho thay đổi lược đồ. GRDB và FMDB cung cấp DatabaseMigrator tương tự.

Tổng kết

  • SQLite là DBMS quan hệ nhúng với cấu hình bằng không, được sử dụng trong mọi ứng dụng di động trên iOS và Android để lưu trữ dữ liệu cục bộ.
  • Giao dịch ACID và chế độ WAL đảm bảo tính toàn vẹn dữ liệu và truy cập đồng thời từ nhiều luồng ứng dụng.
  • Room (Android) và GRDB (iOS) là các trình bao bọc hiện đại trên SQLite giúp đơn giản hóa việc làm việc với cơ sở dữ liệu thông qua API an toàn kiểu và di chuyển tự động.
  • Kiến trúc B-Tree của SQLite đảm bảo tìm kiếm hiệu quả qua chỉ mục, trong khi giao dịch hàng loạt và prepared statements cung cấp hiệu suất ghi cao.
  • SQLite vượt trội hơn Realm và Core Data về tính linh hoạt (tất cả nền tảng), kích thước thư viện và không bị khóa nhà cung cấp.
  • Tối ưu hóa thông qua chỉ mục, chế độ WAL và cài đặt PRAGMA giúp tăng tốc truy vấn gấp 2-3 lần trên khối lượng công việc di động điển hình.
  • Khuyến nghị — sử dụng SQLite làm kho lưu trữ dữ liệu cục bộ chính cho ứng dụng di động thông qua Room trên Android và GRDB trên iOS.

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm