Sqlite

作者: jacky123 | 来源:发表于2016-07-11 22:25 被阅读111次

    前言

    SQLite是一个轻量的、跨平台的、开源的数据库引擎。SQLite每个数据库都是以单个文件(.db)的形式存在,这些数据都是以B-Tree的数据结构形式存储在磁盘上。

    使用SQLiteDatabase的insert,delete等方法或者execSQL方法默认都开启了事务,如果操作的顺利完成才会更新.db数据库。事务的实现是依赖于名为rollback journal文件,借助这个临时文件来完成原子操作和回滚功能。

    大家可以在/data/data/<packageName>/databases/目录下看到一个和数据库同名的.db-journal文件。

    SQLite是文件级别的锁:多个线程可以同时读,但是同时只能有一个线程写。Android提供了SqliteOpenHelper类,加入Java的锁机制以便调用。


    模板

    public class DbOpenHelper extends SQLiteOpenHelper {
     private static final String DB_NAME = "book_provider.db";
     public static final String BOOK_TABLE_NAME = "book";
     public static final String USER_TALBE_NAME = "user";
    
     private static final int DB_VERSION = 3;
    
     private String CREATE_BOOK_TABLE = "CREATE TABLE IF NOT EXISTS "
             + BOOK_TABLE_NAME + "(_id INTEGER PRIMARY KEY," + "name TEXT)";
    
     private String CREATE_USER_TABLE = "CREATE TABLE IF NOT EXISTS "
             + USER_TALBE_NAME + "(_id INTEGER PRIMARY KEY," + "name TEXT," + "sex INT)";
    
     public DbOpenHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); }
    
     @Override    
     public void onCreate(SQLiteDatabase db) {    //如果创建了,就不会回调这个方法。
         db.execSQL(CREATE_BOOK_TABLE);
         db.execSQL(CREATE_USER_TABLE);
     }
    
     @Override
     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
         // TODO ignored
     }
    }
    

    线程问题

    SQLite的同步锁精确到数据库级,粒度比较大,不像别的数据库有表锁,行锁。同一个时间只允许一个连接进行写入操作。

    如果多线程同时读写(这里的指不同的线程用使用的是不同的Helper实例),后面的就会遇到android.database.sqlite.SQLiteException: database is locked这样的异常。对于这样的问题,解决的办法就是keep single sqlite connection,保持单个SqliteOpenHelper实例,同时对所有数据库操作的方法添加synchronized关键字。

    我们常常在多线程中只使用一个SQLiteDatabase引用,在用SQLiteDataBase.close()的时需要注意调是否还有别的线程在使用这个实例。如果一个线程操作完成后就直接close了,别一个正在使用这个数据库的线程就会异常。所以有些人会直接把SQLiteDatabase的实例放在Application中,让它们的生命周期一致。也有的做法是写一个计数器,当计数器为0时才真正关闭数据库。


    使用ORM的问题

    目前网上有很多开源的ORM(对象关系数据映射)框架,如greenDAO、ormlite等等。在使用这些框架有必要很了解一下它们的利弊,特别是一些使用反射的框架,对性能的影响会比较大。有些框架在多线程同步方面也会产生一些问题,所以使用时要有所顾虑。

    Realm 是最近兴起的一个专注于移动设备数据库的库,其核心是使用C++编写,号称很多时候数据的存取速度比SQLite要快很多。不过在我的一些项目中,发现它读取并不比SQLite快。


    参考资料

    相关文章

      网友评论

          本文标题:Sqlite

          本文链接:https://www.haomeiwen.com/subject/ansjjttx.html