简体   繁体   English

SQLite - 数据库被锁定在“PRAGMA journal_mode” - 错误仅针对某些 Android 设备

[英]SQLite - database is locked in "PRAGMA journal_mode" - error only for certain Android devices

Google Play pre-launch report found an issue with my app. Google Play 预发布报告发现我的应用存在问题。 This issue comes up only for a few devices.此问题仅针对少数设备出现。 The problem occurs when I try to open the app for the first time, and the SQLite database is being opened for the first time (after it was copied to the device).当我第一次尝试打开应用程序时出现问题,并且第一次打开 SQLite 数据库(在将其复制到设备之后)。 The app opens fine after this initial incident (for the second time).该应用程序在此初始事件后(第二次)正常打开。

The crash happens at line:崩溃发生在:

mDatabase = SQLiteDatabase.openDatabase(mypath, null, SQLiteDatabase.OPEN_READWRITE);

The code for the database creation:创建数据库的代码:

    /**
     * constructor should be private to prevent direct instantiation.
     * make call to static factory method "getInstance()" instead.
     */
    private DbHelper(Context context) throws SQLException, IOException {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        DB_PATH = Environment.getDataDirectory() + "/data/" + context.getPackageName() + "/databases/";
        helperContext = context;
        boolean dbexist = checkdatabase();
        if (dbexist) {
            open();
        } else {
            createdatabase();
        }
    }

    public void createdatabase() throws IOException {
        boolean dbexist = checkdatabase();
        if(!dbexist) {

            // By calling this method and empty database will be created into
            // the default system path
            // of your application so we are gonna be able to overwrite that
            // database with our database.
            this.getReadableDatabase();
            this.close();
            try {
                copydatabase();
                this.getReadableDatabase();
            } catch(IOException e) {
                throw new Error("Error copying database");
            }
        }
    }

    private boolean checkdatabase() {
        boolean checkdb = false;
        try {
            String myPath = DB_PATH + DATABASE_NAME;
            File dbfile = new File(myPath);
            checkdb = dbfile.exists();
        } catch (SQLiteException e) {
            System.out.println("Database doesn't exist");
        }
        return checkdb;
    }

    private void copydatabase() throws IOException {
        //Open your local db as the input stream
        InputStream myinput = helperContext.getAssets().open(DATABASE_NAME);

        // Path to the just created empty db
        String outfilename = DB_PATH + DATABASE_NAME;

        //Open the empty db as the output stream
        OutputStream myoutput = new FileOutputStream(outfilename);

        // transfer byte to inputfile to outputfile
        byte[] buffer = new byte[1024];
        int length;
        while ((length = myinput.read(buffer)) > 0) {
            myoutput.write(buffer, 0, length);
        }

        //Close the streams
        myoutput.flush();
        myoutput.close();
        myinput.close();
    }

    public void open() throws SQLException {
        //Open the database
        String mypath = DB_PATH + DATABASE_NAME;
        mDatabase = SQLiteDatabase.openDatabase(mypath, null, SQLiteDatabase.OPEN_READWRITE);
    }

    public synchronized void close() {
        if (mDatabase != null) {
            mDatabase.close();
        }
        super.close();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        mDatabase = db;
        try {
            this.createdatabase();
            open();
        }catch(Exception ex){
        }
    }

I was able to reproduce this issue on a simulator, the detailed error log is below:我能够在模拟器上重现这个问题,详细的错误日志如下:

E/SQLiteLog: (5) database is locked in "PRAGMA journal_mode"
E/SQLiteDatabase: Failed to open database '/data/data/com.ch.mo/databases/moDB.db'.
    android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5 SQLITE_BUSY): , while compiling: PRAGMA journal_mode
        at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
        at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1045)
        at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:788)
        at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:405)
        at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:345)
        at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:258)
        at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:205)
        at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:505)
        at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:206)
        at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:198)
        at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:918)
        at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:898)
        at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:789)
        at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:736)
        at com.ch.mo.DbHelper.open(DbHelper.java:128)
        at com.ch.mo.DbHelper.onCreate(DbHelper.java:143)
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:411)
        at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:340)
        at com.ch.mo.DbHelper.createdatabase(DbHelper.java:79)
        at com.ch.mo.DbHelper.<init>(DbHelper.java:67)
        at com.ch.mo.DbHelper.getInstance(DbHelper.java:46)
        at com.ch.mo.MainActivity.onCreate(MainActivity.java:573)
        at android.app.Activity.performCreate(Activity.java:7994)
        at android.app.Activity.performCreate(Activity.java:7978)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
D/CompatibilityChangeReporter: Compat change id reported: 147798919; UID 10121; state: ENABLED
D/HostConnection: HostConnection::get() New Host Connection established 0xf4be3390, tid 3464
D/HostConnection: HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_vulkan_ignored_handles ANDROID_EMU_has_shared_slots_host_memory_allocator ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit ANDROID_EMU_sync_buffer_data ANDROID_EMU_read_color_buffer_dma GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_2 
W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
D/EGL_emulation: eglCreateContext: 0xf4bcd4b0: maj 2 min 0 rcv 2
D/EGL_emulation: eglMakeCurrent: 0xf4bcd4b0: ver 2 0 (tinfo 0xf4f2e4b0) (first time)
I/Gralloc4: mapper 4.x is not supported
D/HostConnection: createUnique: call
    HostConnection::get() New Host Connection established 0xf4bd52b0, tid 3464
D/goldfish-address-space: allocate: Ask for block of size 0x100
D/goldfish-address-space: allocate: ioctl allocate returned offset 0x3f3ffe000 size 0x2000
D/HostConnection: HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_vulkan_ignored_handles ANDROID_EMU_has_shared_slots_host_memory_allocator ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit ANDROID_EMU_sync_buffer_data ANDROID_EMU_read_color_buffer_dma GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_2 
D/AndroidRuntime: Shutting down VM
    
    
    --------- beginning of crash
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.ch.mo, PID: 3434
    java.lang.IllegalStateException: Fragment already added: Songs{e0fd133} (8c0858e6-ae0b-4903-9f34-c790c433860b) id=0x7f08022b android:switcher:2131231275:0}
        at androidx.fragment.app.FragmentStore.addFragment(FragmentStore.java:67)
        at androidx.fragment.app.FragmentManager.addFragment(FragmentManager.java:1563)
        at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:405)
        at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2167)
        at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1990)
        at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1945)
        at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1847)
        at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

The error from the Google automatic test for Google Pixel 3 device: Google Pixel 3 设备的 Google 自动测试错误:

FATAL EXCEPTION: main
Process: com.ch.mo, PID: 20970
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ch.mo/com.ch.mo.MainActivity}: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/com.ch.mo/databases/moDB.db
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2951)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3086)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6718)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/com.ch.mo/databases/moDB.db
    at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
    at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1404)
    at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1347)
    at com.ch.mo.MainActivity.w(:1)
    at com.ch.mo.MainActivity.onCreate(:2)
    at android.app.Activity.performCreate(Activity.java:7144)
    at android.app.Activity.performCreate(Activity.java:7135)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2931)

Thanks for your thoughts on this!感谢您对此的想法!

Checking if the database is closed, and opening it fixed the issue:检查数据库是否关闭,然后打开它解决了问题:

    public void createdatabase() throws SQLException, IOException {
        boolean dbexist = checkdatabase();
        if(!dbexist) {
            // By calling this method and empty database will be created into
            // the default system path
            // of your application so we are gonna be able to overwrite that
            // database with our database.
            if (mDatabase != null && !mDatabase.isOpen())
                this.open();
            this.getReadableDatabase();
            this.close();
            try {
                copydatabase();
                this.getReadableDatabase();
                if (mDatabase != null && !mDatabase.isOpen())
                    this.open();
            } catch(IOException e) {
                throw e;//new Error("Error copying database");
            }
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 SQLite pragma (journal_mode) 语句持久化 - SQLite pragma (journal_mode) statement persistence Android SQLite - 改变 journal_mode - Android SQLite - changing journal_mode SqLite 数据库在 unicode 和 PRAGMA journal_mode 设置时不会关闭 - SqLite database won't close when in unicode and PRAGMA journal_mode is set PHP SQLite PRAGMA journal_mode = wal和只读用户 - PHP SQLite PRAGMA journal_mode = wal and readonly users SQL - SQLiteDatabaseCorruptException - 编译时文件不是数据库:PRAGMA journal_mode - SQL - SQLiteDatabaseCorruptException - file is not a database while compiling: PRAGMA journal_mode 如何在C#中更改Sqlite数据库的“ journal_mode” - How to change “journal_mode” of a Sqlite database in C# 在iOS中使用SQLite PRAGMA同步= OFF和journal_mode = MEMORY进行更新的最坏情况行为 - Worst case behavior for updates using SQLite PRAGMA synchronous = OFF and journal_mode = MEMORY in iOS SQLiteDiskIOException:磁盘 I/O 错误(代码 1802):,编译时:PRAGMA journal_mode - SQLiteDiskIOException: disk I/O error (code 1802): , while compiling: PRAGMA journal_mode 无法打开数据库文件(代码14):,编译时:PRAGMA journal_mode - Unable to open database file (code 14): , while compiling: PRAGMA journal_mode 使用 TCL 更改 SQLite 上的 journal_mode - Change journal_mode on SQLite with TCL
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM