HarmonyOS 应用开发之数据可靠性与安全性&数据库备份与恢复

概述

功能场景

在系统运行中,存储损坏、存储空间不足、文件系统权限、系统掉电等都可能导致数据库发生故障。比如联系人应用的数据库损坏,导致用户的联系人丢失;日历应用的数据库损坏,导致丢失日历提醒等。为此数据管理提供了数据可靠性与安全性相关的解决方案和能力保障。

  • 备份、恢复功能:重要业务应用(如银行)数据丢失,出现严重异常场景,可以通过备份恢复数据库,保证关键数据不丢失。

  • 数据库加密功能:当数据库中存储如认证凭据、财务数据等高敏感信息时,可对数据库进行加密,提高数据库安全性。

  • 数据库分类分级:数据跨设备同步时,数据管理基于数据安全标签和设备安全等级进行访问控制,保证数据安全。

另外,备份数据库存储在应用的沙箱内,当存储空间不足时,可以选择删除本地的数据库备份,释放空间。

基本概念

在进行数据可靠性与安全性相关功能的开发前,请先了解以下相关概念。

数据库备份与恢复

  • 数据库备份 :指对当前数据库的数据库文件进行完整备份。OpenHarmony数据库备份针对数据库全量文件进行完整的备份。

    在进行数据库备份的时候,无需关闭数据库,直接调用对应的数据库备份接口就能完成对数据库文件的备份。

  • 数据库恢复:从指定的备份文件恢复到当前数据库文件。恢复完成时,当前数据库数据恢复到和指定备份文件一致。

数据库加密

数据库加密是对整个数据库文件的加密,可以增强数据库的安全性,有效保护数据库内容。

数据库分类分级

分布式数据管理对数据实施分类分级保护,提供基于数据安全标签以及设备安全等级的访问控制机制。

数据安全标签和设备安全等级越高,加密措施和访问控制措施越严格,数据安全性越高。

运作机制

数据库备份与恢复机制

数据库在备份时,会将当前的数据库备份在指定的文件中,后续对数据库的操作不会影响备份的数据库文件。只有当恢复指定数据库文件时,才会将备份的数据库文件覆盖当前数据库,实现数据的回滚。

  • 键值型数据库备份路径:/data/service/el1(el2)/public/database/...{appId}/kvdb/backup/...{storeId}

  • 关系型数据库备份路径:/data/app/el1(el2)/100/database/...{bundlename}/rdb

数据库加密机制

OpenHarmony数据库加密时,应用开发者无需传入密钥,只需要设置数据库加密的状态即可。系统会自动帮助开发者将数据库加密,使用 huks通用密钥库系统,完成数据库密钥的生成及加密保护。

约束限制

  • 数据库加密的密钥一年自动更换一次。

  • 键值型数据库最多可以备份5份。

  • 键值型数据库的自动备份需要在熄屏且充电的状态下进行。

数据库备份与恢复

场景介绍

当应用在处理一项重要的操作,显然是不能被打断的。例如:写入多个表关联的事务。此时,每个表的写入都是单独的,但是表与表之间的事务关联性不能被分割。

如果操作的过程中出现问题,开发者可以使用恢复功能,将数据库恢复到之前的状态,重新对数据库进行操作。

在数据库被篡改、删除、或者设备断电场景下,数据库可能会因为数据丢失、数据损坏、脏数据等而不可用,可以通过数据库的备份恢复能力将数据库恢复至可用状态。

键值型数据库和关系型数据库均支持对数据库的备份和恢复。另外,键值型数据库还支持删除数据库备份,以释放本地存储空间。

键值型数据库备份、恢复与删除

键值型数据库,通过backup接口实现数据库备份,通过restore接口实现数据库恢复,通过deletebackup接口删除数据库备份。具体接口及功能,可见分布式键值数据库。

  1. 创建数据库。

    (1) 创建kvManager。

    (2) 配置数据库参数。

    (3) 创建kvStore。

    ts 复制代码
    import distributedKVStore from '@ohos.data.distributedKVStore';
    import { BusinessError } from '@ohos.base';
    
    let kvManager: distributedKVStore.KVManager;
    let kvStore: distributedKVStore.SingleKVStore | undefined = undefined;
    let context = getContext(this);
    const kvManagerConfig: distributedKVStore.KVManagerConfig = {
      context: context,
      bundleName: 'com.example.datamanagertest'
    }
    try {
      kvManager = distributedKVStore.createKVManager(kvManagerConfig);
      console.info('Succeeded in creating KVManager.');
      try {
        const options: distributedKVStore.Options = {
          createIfMissing: true,
          encrypt: true,
          backup: false,
          autoSync: true,
          kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION,
          securityLevel: distributedKVStore.SecurityLevel.S1
        };
        kvManager.getKVStore<distributedKVStore.SingleKVStore>('storeId', options, (err, store: distributedKVStore.SingleKVStore) => {
          if (err) {
            console.error(`Failed to get KVStore. Code:${err.code},message:${err.message}`);
            return;
          }
          console.info('Succeeded in getting KVStore.');
          kvStore = store;
        });
      } catch (e) {
        let error = e as BusinessError;
        console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);
      }
    } catch (e) {
      let error = e as BusinessError;
      console.error(`Failed to create KVManager. Code:${error.code},message:${error.message}`);
    }
    
    if (kvStore !== undefined) {
      kvStore = kvStore as distributedKVStore.SingleKVStore;
      //进行后续操作
      //...
    }
  2. 使用put()方法插入数据。

    ts 复制代码
    const KEY_TEST_STRING_ELEMENT = 'key_test_string';
    const VALUE_TEST_STRING_ELEMENT = 'value_test_string';
    try {
      kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, (err) => {
        if (err !== undefined) {
          console.error(`Fail to put data. Code:${err.code},message:${err.message}`);
          return;
        }
        console.info('Succeeded in putting data.');
      });
    } catch (e) {
      let error = e as BusinessError;
      console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);
    }
  3. 使用backup()方法备份数据。

    ts 复制代码
    let file = 'BK001';
    try {
      kvStore.backup(file, (err) => {
        if (err) {
          console.error(`Fail to backup data.code:${err.code},message:${err.message}`);
        } else {
          console.info('Succeeded in backupping data.');
        }
      });
    } catch (e) {
      let error = e as BusinessError;
      console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);
    }
  4. 使用delete()方法删除数据(模拟意外删除、篡改场景)。

    ts 复制代码
    try {
      kvStore.delete(KEY_TEST_STRING_ELEMENT, (err) => {
        if (err !== undefined) {
          console.error(`Fail to delete data. Code:${err.code},message:${err.message}`);
          return;
        }
        console.info('Succeeded in deleting data.');
      });
    } catch (e) {
      let error = e as BusinessError;
      console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);
    }
  5. 使用restore()方法恢复数据。

    ts 复制代码
    let file = 'BK001';
    try {
      kvStore.restore(file, (err) => {
        if (err) {
          console.error(`Fail to restore data. Code:${err.code},message:${err.message}`);
        } else {
          console.info('Succeeded in restoring data.');
        }
      });
    } catch (e) {
      let error = e as BusinessError;
      console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);
    }
  6. 当本地设备存储空间有限或需要重新备份时,还可使用deleteBackup()方法删除备份,释放存储空间。

    ts 复制代码
    let files = ['BK001'];
    try {
      kvStore.deleteBackup(files).then((data) => {
        console.info(`Succeed in deleting Backup. Data:filename is ${data[0]},result is ${data[1]}.`);
      }).catch((err: BusinessError) => {
        console.error(`Fail to delete Backup. Code:${err.code},message:${err.message}`);
      })
    } catch (e) {
      let error = e as BusinessError;
      console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);
    }

关系型数据库备份与恢复

关系型数据库,通过backup接口实现数据库备份,通过restore接口实现数据库恢复。具体接口及功能,可见关系型数据库。

  1. 使用getRdbStore()方法创建关系型数据库。

    ts 复制代码
    import relationalStore from '@ohos.data.relationalStore';
    import { BusinessError } from '@ohos.base';
    
    let store: relationalStore.RdbStore | undefined = undefined;
    
    let context = getContext(this);
    
    const STORE_CONFIG: relationalStore.StoreConfig = {
      name: 'RdbTest.db',
      securityLevel: relationalStore.SecurityLevel.S1
    };
    relationalStore.getRdbStore(context, STORE_CONFIG, (err, rdbStore) => {
      store = rdbStore;
      if (err) {
        console.error(`Failed to get RdbStore. Code:${err.code},message:${err.message}`);
        return;
      }
      store.executeSql('CREATE TABLE IF NOT EXISTS EMPLOYEE (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, AGE INTEGER, SALARY REAL, CODES BLOB)', (err) => {
      })
      console.info('Succeeded in getting RdbStore.');
    })
  2. 使用insert()方法插入数据。

    ts 复制代码
    import { ValuesBucket } from '@ohos.data.ValuesBucket';
    
    let value1 = 'Rose';
    let value2 = 18;
    let value3 = 100.5;
    let value4 = new Uint8Array([1, 2, 3, 4, 5]);
    
    // 以下三种方式可用
    const valueBucket1: ValuesBucket = {
      'NAME': value1,
      'AGE': value2,
      'SALARY': value3,
      'CODES': value4,
    };
    const valueBucket2: ValuesBucket = {
      NAME: value1,
      AGE: value2,
      SALARY: value3,
      CODES: value4,
    };
    const valueBucket3: ValuesBucket = {
      "NAME": value1,
      "AGE": value2,
      "SALARY": value3,
      "CODES": value4,
    };
    
    if(store != undefined) {
      (store as relationalStore.RdbStore).insert('EMPLOYEE', valueBucket1, relationalStore.ConflictResolution.ON_CONFLICT_REPLACE, (err, rowId) => {
        if (err) {
          console.error(`Failed to insert data. Code:${err.code},message:${err.message}`);
          return;
        }
        console.info(`Succeeded in inserting data. rowId:${rowId}`);
      })
    }
  3. 使用backup()方法备份数据。

    ts 复制代码
    if(store != undefined) {
      (store as relationalStore.RdbStore).backup('dbBackup.db', (err) => {
        if (err) {
          console.error(`Failed to backup data. Code:${err.code},message:${err.message}`);
          return;
        }
        console.info('Succeeded in backuping data.');
      })
    }
  4. 使用delete()方法删除数据(模拟意外删除、篡改场景)。

    ts 复制代码
    let predicates = new relationalStore.RdbPredicates('EMPLOYEE');
    predicates.equalTo('NAME', 'Lisa');
    if(store != undefined) {
      (store as relationalStore.RdbStore).delete(predicates).then((rows: number) => {
        console.info(`Delete rows: ${rows}`);
      }).catch((err: BusinessError) => {
        console.error(`Failed to delete data. Code:${err.code},message:${err.message}`);
      })
    }
  5. 使用restore()方法恢复数据。

    ts 复制代码
    if(store != undefined) {
      (store as relationalStore.RdbStore).restore('dbBackup.db', (err) => {
        if (err) {
          console.error(`Failed to restore data. Code:${err.code},message:${err.message}`);
          return;
        }
        console.info('Succeeded in restoring data.');
      })
    }

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ......

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ......

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ......

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题

2.性能优化方向

3.架构方向

4.鸿蒙开发系统底层方向

5.鸿蒙音视频开发方向

6.鸿蒙车载开发方向

7.鸿蒙南向开发方向

相关推荐
科技探秘人2 分钟前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome
科技探秘人2 分钟前
Chrome与傲游浏览器性能与功能的深度对比
前端·chrome
JerryXZR8 分钟前
前端开发中ES6的技术细节二
前端·javascript·es6
七星静香10 分钟前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
q24985969312 分钟前
前端预览word、excel、ppt
前端·word·excel
小华同学ai18 分钟前
wflow-web:开源啦 ,高仿钉钉、飞书、企业微信的审批流程设计器,轻松打造属于你的工作流设计器
前端·钉钉·飞书
Gavin_91527 分钟前
【JavaScript】模块化开发
前端·javascript·vue.js
懒大王爱吃狼2 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
瓜牛_gn2 小时前
mysql特性
数据库·mysql
奶糖趣多多3 小时前
Redis知识点
数据库·redis·缓存