• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Database Backup and Restore (ArkTS)
2
3## When to Use
4
5You may need to restore a database in any of the following cases:
6
7An important operation being performed by an application is interrupted.
8
9The database is unavailable due to data loss or corruption, or dirty data.
10
11
12Both KV stores and RDB stores support database backup and restore. You can also delete KV store backups to release local storage space.
13
14
15## Backing Up, Restoring, and Deleting a KV Store
16
17You can use **backup()** to back up a KV store, use **restore()** to restore a KV store, and use **deletebackup()** to delete a KV store backup file. For details about the APIs, see [Distributed KV Store](../reference/apis-arkdata/js-apis-distributedKVStore.md).
18
191. Create a KV store.
20
21   (1) Create a **kvManager** instance.
22
23   (2) Set database parameters.
24
25   (3) Create a **kvStore** instance.
26
27
28   ```ts
29   import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
30   import { hilog } from '@kit.PerformanceAnalysisKit';
31   import { distributedKVStore } from '@kit.ArkData';
32   import { BusinessError } from '@kit.BasicServicesKit';
33
34   export default class EntryAbility extends UIAbility {
35     onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
36       this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
37       hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
38       let kvManager: distributedKVStore.KVManager;
39       let kvStore: distributedKVStore.SingleKVStore | undefined = undefined;
40       let context = this.context;
41       const kvManagerConfig: distributedKVStore.KVManagerConfig = {
42         context: context,
43         bundleName: 'com.example.datamanagertest'
44       }
45       try {
46         kvManager = distributedKVStore.createKVManager(kvManagerConfig);
47         console.info('Succeeded in creating KVManager.');
48         try {
49           const options: distributedKVStore.Options = {
50             createIfMissing: true,
51             encrypt: true,
52             backup: false,
53             autoSync: false,
54             kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION,
55             securityLevel: distributedKVStore.SecurityLevel.S3
56           };
57           kvManager.getKVStore<distributedKVStore.SingleKVStore>('storeId', options, (err, store: distributedKVStore.SingleKVStore) => {
58             if (err) {
59               console.error(`Failed to get KVStore. Code:${err.code},message:${err.message}`);
60               return;
61             }
62             console.info('Succeeded in getting KVStore.');
63             kvStore = store;
64           });
65         } catch (e) {
66           let error = e as BusinessError;
67           console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);
68         }
69       } catch (e) {
70         let error = e as BusinessError;
71         console.error(`Failed to create KVManager. Code:${error.code},message:${error.message}`);
72       }
73
74       if (kvStore !== undefined) {
75         kvStore = kvStore as distributedKVStore.SingleKVStore;
76         // Perform subsequent operations.
77         //...
78       }
79     }
80   }
81   ```
82
832. Call **put()** to insert data to the KV store.
84
85   ```ts
86   const KEY_TEST_STRING_ELEMENT = 'key_test_string';
87   const VALUE_TEST_STRING_ELEMENT = 'value_test_string';
88   try {
89     kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, (err) => {
90       if (err !== undefined) {
91         console.error(`Fail to put data. Code:${err.code},message:${err.message}`);
92         return;
93       }
94       console.info('Succeeded in putting data.');
95     });
96   } catch (e) {
97     let error = e as BusinessError;
98     console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);
99   }
100   ```
101
1023. Call **backup()** to back up the KV store.
103
104   ```ts
105   let backupFile = 'BK001';
106   try {
107     kvStore.backup(backupFile, (err) => {
108       if (err) {
109         console.error(`Fail to backup data.code:${err.code},message:${err.message}`);
110       } else {
111         console.info('Succeeded in backuping data.');
112       }
113     });
114   } catch (e) {
115     let error = e as BusinessError;
116     console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);
117   }
118   ```
119
1204. Call **delete()** to delete data to simulate unexpected deletion or data tampering.
121
122   ```ts
123   try {
124     kvStore.delete(KEY_TEST_STRING_ELEMENT, (err) => {
125       if (err !== undefined) {
126         console.error(`Fail to delete data. Code:${err.code},message:${err.message}`);
127         return;
128       }
129       console.info('Succeeded in deleting data.');
130     });
131   } catch (e) {
132     let error = e as BusinessError;
133     console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);
134   }
135   ```
136
1375. Call **restore()** to restore the KV store.
138
139   ```ts
140   try {
141     kvStore.restore(backupFile, (err) => {
142       if (err) {
143         console.error(`Fail to restore data. Code:${err.code},message:${err.message}`);
144       } else {
145         console.info('Succeeded in restoring data.');
146       }
147     });
148   } catch (e) {
149     let error = e as BusinessError;
150     console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);
151   }
152   ```
153
1546. Call **deleteBackup()** to delete the backup file to release storage space.
155
156   ```ts
157   let files = [backupFile];
158   try {
159     kvStore.deleteBackup(files).then((data) => {
160       console.info(`Succeed in deleting Backup. Data:filename is ${data[0]},result is ${data[1]}.`);
161     }).catch((err: BusinessError) => {
162       console.error(`Fail to delete Backup. Code:${err.code},message:${err.message}`);
163     })
164   } catch (e) {
165     let error = e as BusinessError;
166     console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);
167   }
168   ```
169
170## Backing Up an RDB Store
171
172A database backup can be used to quickly restore an RDB store in abnormal state.
173
174Two backup modes are available: manual backup and automatic backup. Automatic backup is available only for system applications.
175
176### Manual Backup
177
178Call the [backup](../reference/apis-arkdata/arkts-apis-data-relationalStore-RdbStore.md#backup) API to manually back up an RDB store. <br>Example:
179
180```ts
181import { UIAbility } from '@kit.AbilityKit';
182import { relationalStore } from '@kit.ArkData';
183import { BusinessError } from '@kit.BasicServicesKit';
184
185export default class EntryAbility extends UIAbility {
186  async onCreate(): Promise<void> {
187    let store: relationalStore.RdbStore | undefined = undefined;
188    let context = this.context;
189
190    const STORE_CONFIG: relationalStore.StoreConfig = {
191      name: 'RdbTest.db',
192      securityLevel: relationalStore.SecurityLevel.S3,
193      allowRebuild: true
194    };
195    try {
196      store = await relationalStore.getRdbStore(context, STORE_CONFIG);
197      await store.executeSql('CREATE TABLE IF NOT EXISTS EMPLOYEE (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, AGE INTEGER, SALARY REAL, CODES BLOB)');
198      console.info('Succeeded in getting RdbStore.');
199    } catch (e) {
200      const err = e as BusinessError;
201      console.error(`Failed to get RdbStore. Code:${err.code},message:${err.message}`);
202    }
203
204    if (!store) {
205      return;
206    }
207
208    try {
209      /**
210       * Backup.db specifies the database backup file. By default, it is in the same directory as the RDB store.
211       * You can also specify an absolute path, for example, /data/storage/el2/database/Backup.db. The file path must exist and will not be automatically created.
212       */
213      await store.backup("Backup.db");
214      console.info(`Succeeded in backing up RdbStore.`);
215    } catch (e) {
216      const err = e as BusinessError;
217      console.error(`Failed to backup RdbStore. Code:${err.code}, message:${err.message}`);
218    }
219  }
220}
221```
222
223<!--Del-->
224
225### Automatic Backup (for System Applications Only)
226
227To implement hot backup of an RDB store, set **haMode** in [StoreConfig](../reference/apis-arkdata/js-apis-data-relationalStore-sys.md#storeconfig) to **MAIN_REPLICA**. This parameter is available only for system applications. <br>Example:
228
229```ts
230import { UIAbility } from '@kit.AbilityKit';
231import { relationalStore } from '@kit.ArkData';
232import { BusinessError } from '@kit.BasicServicesKit';
233
234export default class EntryAbility extends UIAbility {
235  async onCreate(): Promise<void> {
236    let store: relationalStore.RdbStore | undefined = undefined;
237    let context = this.context;
238    try {
239      // Set haMode of StoreConfig to MAIN_REPLICA.
240      const AUTO_BACKUP_CONFIG: relationalStore.StoreConfig = {
241        name: "BackupRestoreTest.db",
242        securityLevel: relationalStore.SecurityLevel.S3,
243        haMode: relationalStore.HAMode.MAIN_REPLICA, // Data is written to the main and replica stores on a real-time basis.
244        allowRebuild: true
245      }
246
247      // Call getRdbStore() to create an RDB store instance.
248      store = await relationalStore.getRdbStore(context, AUTO_BACKUP_CONFIG);
249      console.info('Succeeded in getting RdbStore.');
250    } catch (e) {
251      const err = e as BusinessError;
252      console.error(`Failed to get RdbStore. Code:${err.code}, message:${err.message}`);
253    }
254  }
255}
256```
257
258<!--DelEnd-->
259
260## Rebuilding an RDB Store
261
262If error 14800011 is displayed when an RDB store is created or used, an exception occurs in the database. You can delete the database and restore data.
263
264You can set **allowRebuild** in [StoreConfig](../reference/apis-arkdata/arkts-apis-data-relationalStore-i.md#storeconfig) to **true**, which allows the database to be automatically deleted when an exception occurs. The newly rebuilt RDB store is empty. You need to create tables and restore data from the database backup. For details about how to back up RDB store data, see [Backing Up an RDB Store](#backing-up-an-rdb-store). For details about how to restore RDB store data, see [Restoring RDB Store Data](#restoring-rdb-store-data).
265
266If **allowRebuild** in **StoreConfig** is set to **true** before the database is abnormal, the database will be automatically deleted when an exception occurs.
267
268If **allowRebuild** in **StoreConfig** is not set or is set to **false**, set **allowRebuild** to **true** and open the rebuilt RDB store. <br>Example:
269
270```ts
271import { UIAbility } from '@kit.AbilityKit';
272import { relationalStore } from '@kit.ArkData';
273import { BusinessError } from '@kit.BasicServicesKit';
274
275export default class EntryAbility extends UIAbility {
276  async onCreate(): Promise<void> {
277    let store: relationalStore.RdbStore | undefined = undefined;
278    let context = this.context;
279    try {
280      const STORE_CONFIG: relationalStore.StoreConfig = {
281        name: 'RdbTest.db',
282        securityLevel: relationalStore.SecurityLevel.S3,
283        allowRebuild: true
284      };
285      store = await relationalStore.getRdbStore(context, STORE_CONFIG);
286      await store.executeSql('CREATE TABLE IF NOT EXISTS EMPLOYEE (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, AGE INTEGER, SALARY REAL, CODES BLOB)');
287      console.info('Succeeded in getting RdbStore.');
288    } catch (e) {
289      const err = e as BusinessError;
290      console.error(`Failed to get RdbStore. Code:${err.code}, message:${err.message}`);
291    }
292  }
293}
294```
295
296## Restoring RDB Store Data
297
298If an RDB store is abnormal, you can restore it by using the database backup.
299
300You can restore data from either the manual backup data or automatic backup data. The latter is available only for system applications.
301
302### Restoring from Manual Backup Data
303
304You can use **backup()** to [perform manual backup](#manual-backup) and use **restore()** to restore data from the manual backup data.
305
306The following example contains only the code snippet for the restore process. The complete code must also contain the code for backing up data and rebuilding an RDB store.
307
3081. Throws an error code to indicate a database exception.
309
310   ```ts
311   let predicates = new relationalStore.RdbPredicates("EMPLOYEE");
312   if (store != undefined) {
313     (store as relationalStore.RdbStore).query(predicates, ["ID", "NAME", "AGE", "SALARY", "CODES"]).then((result: relationalStore.ResultSet) => {
314       let resultSet = result;
315       try {
316         /* ...
317            Logic for adding, deleting, and modifying data.
318            ...
319         */
320         // Throw an exception.
321         if (resultSet?.rowCount == -1) {
322           resultSet ?.isColumnNull(0);
323         }
324         // Call other APIs such as resultSet.goToFirstRow() and resultSet.count(), which also throw exceptions.
325         while (resultSet.goToNextRow()) {
326           console.info(JSON.stringify(resultSet.getRow()))
327         }
328         resultSet.close();
329       } catch (err) {
330           if (err.code === 14800011) {
331              // Perform step 2 (close result sets and then restore data).
332           }
333           console.error(JSON.stringify(err));
334       }
335     })
336   }
337   ```
338
3392. Close all opened result sets.
340
341   ```ts
342   // Obtain all opened result sets.
343   let resultSets: Array<relationalStore.ResultSet> = [];
344   // Call resultSet.close() to close all opened result sets.
345   for (let resultSet of resultSets) {
346     try {
347       resultSet.close();
348     } catch (e) {
349         if (e.code !== 14800014) {
350           console.error(`Code:${e.code}, message:${e.message}`);
351         }
352     }
353   }
354   ```
355
3563. Call **restore()** to restore data.
357
358   ```ts
359   import { UIAbility } from '@kit.AbilityKit';
360   import { relationalStore } from '@kit.ArkData';
361   import { BusinessError } from '@kit.BasicServicesKit';
362   import { fileIo } from '@kit.CoreFileKit';
363
364   export default class EntryAbility extends UIAbility {
365     async onCreate(): Promise<void> {
366       let store: relationalStore.RdbStore | undefined = undefined;
367       let context = this.context;
368       let STORE_CONFIG: relationalStore.StoreConfig = {
369         name: "RdbTest.db",
370         securityLevel: relationalStore.SecurityLevel.S3,
371         allowRebuild: true
372       }
373       try {
374         /**
375          * Backup.db specifies the database backup file. By default, it is in the same directory as the current database.
376          * If an absolute path is specified for the database backup file, for example, /data/storage/el2/database/Backup.db, pass in the absolute path.
377          */
378         let backupFilePath = context.databaseDir + '/rdb/Backup.db';
379         const backupExist = await fileIo.access(backupFilePath);
380         if (!backupExist) {
381           console.info("Backup is not exist.");
382           // Open the rebuilt RDB store and create tables.
383           // Generate data.
384           return;
385         }
386       } catch (e) {
387         console.error(`Code:${e.code}, message:${e.message}`);
388       }
389
390       try {
391         store = await relationalStore.getRdbStore(context, STORE_CONFIG);
392         // Call restore() to restore data.
393         await store.restore("Backup.db");
394         console.log("Restore from back success.")
395       } catch (e) {
396         const err = e as BusinessError;
397         console.error(`Failed to get RdbStore. Code:${err.code}, message:${err.message}`);
398       }
399     }
400   }
401   ```
402
403<!--Del-->
404
405### Restoring from Automatic Backup Data (for System Applications Only)
406
407Call [restore()](../reference/apis-arkdata/js-apis-data-relationalStore-sys.md#restore12) to restore data from the [automatic backup data](#automatic-backup-for-system-applications-only). Only system applications support this operation.
408
409The following example contains only the code snippet for the restore process. The complete code must also contain the code for backing up data and rebuilding an RDB store.
410
411   ```ts
412   if (store !== undefined) {
413     try {
414       // Add, delete, modify, and query data.
415     } catch (err) {
416         if (err.code == 14800011) {
417           // Obtain all opened result sets.
418           let resultSets: Array<relationalStore.ResultSet> = [];
419           // Call resultSet.close() to close all opened result sets.
420           for (let resultSet of resultSets) {
421             try {
422               resultSet.close();
423             } catch (e) {
424                 if (e.code !== 14800014) {
425                   console.error(`Code:${e.code}, message:${e.message}`);
426                 }
427             }
428           }
429
430           (store as relationalStore.RdbStore).restore("Backup.db", (err: BusinessError) => {
431             if (err) {
432               console.error(`Failed to restore RdbStore. Code:${err.code}, message:${err.message}`);
433               return;
434             }
435             console.info(`Succeeded in restoring RdbStore.`);
436           })
437         }
438         console.error(`Code:${err.code}, message:${err.message}`);
439     }
440   }
441   ```
442
443<!--DelEnd-->
444
445<!--RP1--><!--RP1End-->
446