GVKun编程网logo

SQLiteDatabase多线程锁定模式

29

本文的目的是介绍SQLiteDatabase多线程锁定模式的详细情况,我们将通过专业的研究、有关数据的分析等多种方式,同时也不会遗漏关于AndroidDataBase被其他线程锁定、androidSQ

本文的目的是介绍SQLiteDatabase多线程锁定模式的详细情况,我们将通过专业的研究、有关数据的分析等多种方式,同时也不会遗漏关于Android DataBase被其他线程锁定、android SQLiteDatabase、android – SQLiteDatabase getWritableDatabase()无法正常工作、android – SQLiteDatabase.openDatabase vs SQLiteOpenHelper.getReadableDatabase的知识。

本文目录一览:

SQLiteDatabase多线程锁定模式

SQLiteDatabase多线程锁定模式

我使用此类来管理与基础SQLiteDatabase的连接

public class BasicDataSource {    protected DatabaseHandler dbHelper;    protected volatile SQLiteDatabase readable_database;    protected volatile SQLiteDatabase writable_database;    protected Object read_lock = new Object();    protected Object write_lock = new Object();    protected Context context;    protected BasicDataSource(Context ctx) {        dbHelper = DatabaseHandler.getInstance(ctx);        getReadableDatabase();        dbHelper.onCreate(getWritableDatabase());        this.context = ctx;    }    public synchronized void close() {        dbHelper.close();    }    protected void closeInsertHelpers(InsertHelper... helpers) {        for (InsertHelper ih : helpers) {            if (ih != null)                ih.close();        }    }    protected SQLiteDatabase getReadableDatabase() {        synchronized (read_lock) {            if (readable_database == null || !readable_database.isOpen()) {                readable_database = dbHelper.getReadableDatabase();            }            return readable_database;        }    }    protected SQLiteDatabase getWritableDatabase() {        synchronized (write_lock) {            if (writable_database == null || !writable_database.isOpen()) {                writable_database = dbHelper.getWritableDatabase();            }            return writable_database;        }    }    protected synchronized void open() throws SQLException {        getReadableDatabase();        getWritableDatabase();    }}

它包含两个锁,一个用于读取,第二个用于写入。但是我仍然偶尔会遇到这种例外情况:

java.lang.RuntimeException: An error occured while executing doInBackground()        at android.os.AsyncTask$3.done(AsyncTask.java:299)        at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)        at java.util.concurrent.FutureTask.setException(FutureTask.java:124)        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)        at java.util.concurrent.FutureTask.run(FutureTask.java:137)        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)        at java.lang.Thread.run(Thread.java:856)Caused by: android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5): , while compiling: PRAGMA journal_mode        at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)        at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:882)        at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:627)        at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:313)        at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:287)        at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:215)        at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)        at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)        at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)        at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)        at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)        at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)        at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)        at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:804)        at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)        at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)        at com.mycompany.myapplication.sql.BasicDataSource.getWritableDatabase(BasicDataSource.java:57)        at com.mycompany.myapplication.sql.datasources.SomeDataSource.fillUpDatabaseMethod(SomeDataSource.java:264)        at com.mycompany.myapplication.sql.datasources.SomeDataSource.renewCacheMethod(SomeDataSource.java:560)        at com.mycompany.myapplication.activities.lists.ListsActivity$Worker.doInBackground(ListsActivity.java:315)        at com.mycompany.myapplication.activities.lists.ListsActivity$Worker.doInBackground(ListsActivity.java:1)        at android.os.AsyncTask$2.call(AsyncTask.java:287)        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)        ... 4 moreandroid.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5): , while compiling: PRAGMA journal_mode        at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)        at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:882)        at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:627)        at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:313)        at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:287)        at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:215)        at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)        at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)        at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)        at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)        at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)        at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)        at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)        at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:804)        at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)        at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)        at com.mycompany.myapplication.sql.BasicDataSource.getWritableDatabase(BasicDataSource.java:57)        at com.mycompany.myapplication.sql.datasources.SomeDataSource.fillUpDatabaseMethod(SomeDataSource.java:264)        at com.mycompany.myapplication.sql.datasources.SomeDataSource.renewCacheMethod(SomeDataSource.java:560)        at com.mycompany.myapplication.activities.lists.ListsActivity$Worker.doInBackground(ListsActivity.java:315)        at com.mycompany.myapplication.activities.lists.ListsActivity$Worker.doInBackground(ListsActivity.java:1)        at android.os.AsyncTask$2.call(AsyncTask.java:287)        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)        at java.util.concurrent.FutureTask.run(FutureTask.java:137)        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)        at java.lang.Thread.run(Thread.java:856)

这意味着,在尝试获取getWritableDatabase中的锁定时,数据库以某种方式被锁定。

我的SQLiteOpenHelper是单例模式,并且DataSources仅使用BasicDataSource作为父类。

我可以做些什么来避免在显示的代码中出现SQLiteDatabaseLockedException?

答案1

小编典典

在SQLite中,可以有任意多个读取器,但是任何写入器都会阻止所有其他读取器和写入器。

读者和作家都必须使用一个锁。

请注意,只要您实际访问数据库,就必须保持锁定。


如果要支持多个阅读器,请使用实现的锁ReadWriteLock,例如ReentrantReadWriteLock。像这样:

class MyData {    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();    private final Lock r = rwl.readLock();    private final Lock w = rwl.writeLock();    public Data ReadSomething(int id) {        r.lock();        try {            Cursor c = readableDatabase.query(...);            return c.getString(0);        } finally {            r.unlock();        }    }    public void ChangeSomething(int id, int value) {        w.lock();        try {            writeableDatabase.update(...);        } finally {            w.unlock();        }    }}

Android DataBase被其他线程锁定

Android DataBase被其他线程锁定

我正在使用 android sqlite数据库,我无法在DataBase中插入记录.
在代码中,我在启动应用程序时只打开一次数据库,并在那里设置了我的Application类变量的引用,以便我可以从代码的任何部分访问数据库,这很好.

问题是:我可以访问数据库,但我无法启动事务.它没有给我任何异常,但sqliteDatabaseWrite.isDbLockedByOtherThreads()返回TRUE.此外,在logcat中有一条警告消息:

WARN/sqliteDatabase(19006): database lock has not been available for
30 sec. Current Owner of the lock is 1. Continuing to wait in thread:
14

任何解决方案?

解决方法

谢谢你和我在一起.其实我解决了我的问题.我使用sqliteDatabase.beginTransaction()启动了一个sqlite数据库操作,我忘了结束此事务.我通过结束交易解决了这个问题.为了结束事务,我使用了以下代码:

sqliteDatabase.setTransactionSuccessful();
sqliteDatabase.endTransaction();

谢谢.

android SQLiteDatabase

android SQLiteDatabase

转载地址: http://blog.sina.com.cn/s/blog_6fff321b0100onw8.html

SQLiteDatabase

[功能]

SQLiteDatabase 是关于数据库操作的 可用于 insert delete update query 等操作可惜美中不足的是:

1. 其不支持创建数据库

2. 其不支持版本更新 或者说其不知道如何做 因为具体数据的差异

鉴于以上的缺陷 有一个辅助类可以完成上面功能 那就是:SQLiteOpenHelper

[代码]

1. 定义 SQLiteOpenHelper 并完成 创建 更新 功能

  1. publicclassDBHelper extendsSQLiteOpenHelper { 
  2. publicstaticfinalString TB_NAME = "mycountry"
  3. publicstaticfinalString ID = "_id"
  4. publicstaticfinalString COUNTRY = "country"
  5. publicstaticfinalString CODE = "code"
  6. publicDBHelper(Context context, String name, 
  7. CursorFactory factory,intversion) { 
  8. super(context, name, factory, version); 
  9. publicvoidonCreate(SQLiteDatabase db) { 
  10. db.execSQL("CREATE TABLE IF NOT EXISTS "
  11. + TB_NAME + " ("
  12. + ID + " INTEGER PRIMARY KEY,"
  13. + COUNTRY + " VARCHAR,"
  14. + CODE + " INTEGER)"); 
  15. publicvoidonUpgrade(SQLiteDatabase db, 
  16. intoldVersion, intnewVersion) { 
  17. //TODO 删除数据库之前 做数据备份
  18. db.execSQL("DROP TABLE IF EXISTS "+TB_NAME); 
  19. onCreate(db); 

2. 从 SQLiteOpenHelper 得到 SQLiteDatabase 的实例

  1. DBHelper helper = newDBHelper(this, DB_NAME, null, VERSION); 
  2. SQLiteDatabase db = helper.getWritableDatabase(); 

3. SQLiteDatabase 的一些操作:

* 插入数据:

  1. ContentValues values = newContentValues(); 
  2. values.put(DBHelper.COUNTRY, "中国"); 
  3. values.put(DBHelper.CODE, 86); 
  4. db.insert(DBHelper.TB_NAME,DBHelper.ID, values); 

* 改动数据

  1. db.insert(DBHelper.TB_NAME,DBHelper.ID,null); 
  2. values.clear(); 
  3. values.put(DBHelper.COUNTRY, "意大利"); 
  4. values.put(DBHelper.CODE, 39); 
  5. db.update(DBHelper.TB_NAME, values,DBHelper.ID + " = 2",null); 

* execSQL 执行 SQL 语言

  1. db.execSQL("INSERT INTO "
  2. + DBHelper.TB_NAME + "("
  3. + DBHelper.COUNTRY + ","
  4. + DBHelper.CODE + ") VALUES "
  5. "('' 洪都拉斯 '',504)"); 

* 查询数据

  1. Cursor c = db.query(DBHelper.TB_NAME,null,null,null,null,null
  2. DBHelper.CODE+" DESC"); 

* 删除数据所有数据

  1. db.delete(DBHelper.TB_NAME,null,null); 

数据库的生成 调用 getWiterAbleDatabase getReadAbleDatabase 生成数据库 i

android 嵌入式数据库 为单用户数据库 所以 可以不调用 db.close () 来关闭数据库这样反而可以提高性能

android – SQLiteDatabase getWritableDatabase()无法正常工作

android – SQLiteDatabase getWritableDatabase()无法正常工作

我收到了错误

02-15 08:36:13.097: I/sqliteDatabaseCpp(404): sqlite returned: error
code = 1,msg = near “null”: Syntax error,
db=/data/data/com.lifeApp/databases/contactsManager

在我的代码的第157行.这是该方法下的部分

getAllContacts()

无效的代码是

sqliteDatabase db = this.getWritableDatabase();

完整示例:

package com.lifeApp;

import android.content.Context;
import android.database.sqlite.sqliteDatabase;
import android.database.sqlite.sqliteOpenHelper;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.database.Cursor;

public class DatabaseHandler extends sqliteOpenHelper {

   // All Static variables
   // Database Version
   private static final int DATABASE_VERSION = 1;

   // Database Name
   private static final String DATABASE_NAME = "contactsManager";

   // Contacts table name
   private static final String TABLE_CONTACTS = "contacts";

   // Contacts Table Columns names
   private static final String KEY_ID = "id";
   private static final String FirsTNAME = "firstname";
   private static final String LASTNAME = "lastname";
   private static final String PASSWORD = "password";
   private static final String EMAIL = "email";

   private static final String KEY_PH_NO = "phone_number";

private static final String KEY_NAME = null;

   public DatabaseHandler(Context context) {
       super(context,DATABASE_NAME,null,DATABASE_VERSION);
   }

   // Creating Tables
   @Override
   public void onCreate(sqliteDatabase db) {

       String CREATE_CONTACTS_TABLE = "CREATE TABLE " + TABLE_CONTACTS + "("
               + KEY_ID + " INTEGER PRIMARY KEY," 
               + KEY_NAME + " TEXT,"
               + FirsTNAME + " TEXT,"
               + LASTNAME + " TEXT,"
               + PASSWORD  + " TEXT"
               + EMAIL + " TEXT"
               + KEY_PH_NO + " TEXT" + ")";
       db.execsql(CREATE_CONTACTS_TABLE);
   }

   // Upgrading database
   @Override
   public void onUpgrade(sqliteDatabase db,int oldVersion,int newVersion) {
       // Drop older table if existed
       db.execsql("DROP TABLE IF EXISTS " + TABLE_CONTACTS);

       // Create tables again
       onCreate(db);
   }

   /**
    * All CRUD(Create,Read,Update,Delete) Operations
    */

   // Adding new contact
   void addContact(Contact contact) {
       sqliteDatabase db = this.getWritableDatabase();

       ContentValues values = new ContentValues();
       values.put(KEY_NAME,contact.getName()); // Contact Name
       values.put(FirsTNAME,contact.getFirstname());
       values.put(LASTNAME,contact.getLastname());
       values.put(EMAIL,contact.getEmail());
       values.put(PASSWORD,contact.getpassword());
       values.put(KEY_PH_NO,contact.getPhoneNumber()); // Contact Phone

       // Inserting Row
       db.insert(TABLE_CONTACTS,values);
       db.close(); // Closing database connection
   }

   // Getting single contact
   Contact getContact(int id) {
       sqliteDatabase db = this.getReadableDatabase();

       Cursor cursor = db.query(TABLE_CONTACTS,new String[] { KEY_ID,KEY_NAME,KEY_PH_NO },KEY_ID + "=?",new String[] { String.valueOf(id) },null);
       if (cursor != null)
           cursor.movetoFirst();

       Contact contact = new Contact(Integer.parseInt(cursor.getString(0)),cursor.getString(1),cursor.getString(2),cursor.getString(3),cursor.getString(4),cursor.getString(5),cursor.getString(6));
       // return contact
       return contact;
   }

   // Getting All Contacts
   public List<Contact> getAllContacts() {
       List<Contact> contactList = new ArrayList<Contact>();
       // Select All Query
       String selectQuery = "SELECT  * FROM " + TABLE_CONTACTS;

       sqliteDatabase db = this.getWritableDatabase();
       Cursor cursor = db.rawQuery(selectQuery,null);

       // looping through all rows and adding to list
       if (cursor.movetoFirst()) {
           do {
               Contact contact = new Contact();
               contact.setID(Integer.parseInt(cursor.getString(0)));
               contact.setFirstname(cursor.getString(1));
               contact.setLastname(cursor.getString(2));
               contact.setPassword(cursor.getString(3));
               contact.setEmail(cursor.getString(4));
               // Adding contact to list
               contactList.add(contact);
           } while (cursor.movetoNext());
       }

       // return contact list
       return contactList;
   }

   // Updating single contact
   public int updateContact(Contact contact) {
       sqliteDatabase db = this.getWritableDatabase();

       ContentValues values = new ContentValues();
       values.put(KEY_NAME,contact.getName());
       values.put(FirsTNAME,contact.getLastname());
       values.put(PASSWORD,contact.getpassword());
       values.put(EMAIL,contact.getEmail());
       values.put(KEY_PH_NO,contact.getPhoneNumber());

       // updating row
       return db.update(TABLE_CONTACTS,values,KEY_ID + " = ?",new String[] { String.valueOf(contact.getID()) });
   }

   // Deleting single contact
   public void deleteContact(Contact contact) {
       sqliteDatabase db = this.getWritableDatabase();
       db.delete(TABLE_CONTACTS,new String[] { String.valueOf(contact.getID()) });
       db.close();
   }

   // Getting contacts Count
   public int getContactsCount() {
       String countQuery = "SELECT  * FROM " + TABLE_CONTACTS;
       sqliteDatabase db = this.getReadableDatabase();
       Cursor cursor = db.rawQuery(countQuery,null);
       cursor.close();

       // return count
       return cursor.getCount();
   }

}

解决方法

在CREATE_CONTACTS_TABLE中,您会遗漏一些逗号

String CREATE_CONTACTS_TABLE = "CREATE TABLE " + TABLE_CONTACTS + "("
           + KEY_ID + " INTEGER PRIMARY KEY," 
           + KEY_NAME + " TEXT,"
           + FirsTNAME + " TEXT,"
           + LASTNAME + " TEXT,"
           + PASSWORD  + " TEXT"           <==
           + EMAIL + " TEXT"               <==
           + KEY_PH_NO + " TEXT" + ")";
   db.execsql(CREATE_CONTACTS_TABLE);

android – SQLiteDatabase.openDatabase vs SQLiteOpenHelper.getReadableDatabase

android – SQLiteDatabase.openDatabase vs SQLiteOpenHelper.getReadableDatabase

这两种方法有什么区别吗?两者都返回一个打开的sqlite Database.如果不存在,则两者都可以创建数据库.当需要读/写时,sqliteOpenHelper也有getWriteableDatabase …

我应该使用哪种方法?基于我见过的示例代码,我首先使用sqliteOpenHelper创建数据库,但在需要使用数据库时调用sqliteDatabase.openDatabase.

解决方法

openDatabase()更灵活,允许您指定区域设置等,但在大多数情况下,您不需要显式提供这些详细信息,Android documentation说使用getReadableDatabase()和getWriteableDatabase().

关于SQLiteDatabase多线程锁定模式的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于Android DataBase被其他线程锁定、android SQLiteDatabase、android – SQLiteDatabase getWritableDatabase()无法正常工作、android – SQLiteDatabase.openDatabase vs SQLiteOpenHelper.getReadableDatabase等相关内容,可以在本站寻找。

本文标签: