概述
功能场景
在系统运行中,存储损坏、存储空间不足、文件系统权限、系统掉电等都可能导致数据库发生故障。比如联系人应用的数据库损坏,导致用户的联系人丢失;日历应用的数据库损坏,导致丢失日历提醒等。为此数据管理提供了数据可靠性与安全性相关的解决方案和能力保障。
备份、恢复功能:重要业务应用(如银行)数据丢失,出现严重异常场景,可以通过备份恢复数据库,保证关键数据不丢失。
数据库加密功能:当数据库中存储如认证凭据、财务数据等高敏感信息时,可对数据库进行加密,提高数据库安全性。
数据库分类分级:数据跨设备同步时,数据管理基于数据安全标签和设备安全等级进行访问控制,保证数据安全。
另外,备份数据库存储在应用的沙箱内,当存储空间不足时,可以选择删除本地的数据库备份,释放空间。
基本概念
在进行数据可靠性与安全性相关功能的开发前,请先了解以下相关概念。
数据库备份与恢复
数据库备份:指对当前数据库的数据库文件进行完整备份。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) 创建kvManager。
(2) 配置数据库参数。
(3) 创建kvStore。
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;
//进行后续操作
//...
}
-
使用put()方法插入数据。
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}`); }
-
使用backup()方法备份数据。
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}`); }
-
使用delete()方法删除数据(模拟意外删除、篡改场景)。
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}`); }
-
使用restore()方法恢复数据。
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}`); }
-
当本地设备存储空间有限或需要重新备份时,还可使用deleteBackup()方法删除备份,释放存储空间。
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接口实现数据库恢复。具体接口及功能,可见关系型数据库。
-
使用getRdbStore()方法创建关系型数据库。
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.'); })
-
使用insert()方法插入数据。
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}`); }) }
-
使用backup()方法备份数据。
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.'); }) }
-
使用delete()方法删除数据(模拟意外删除、篡改场景)。
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}`); }) }
-
使用restore()方法恢复数据。
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.'); }) }
写在最后
- 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
- 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
- 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
- 想要获取更多完整鸿蒙最新学习知识点,请移步前往小编:
https://gitee.com/MNxiaona/733GH/blob/master/jianshu