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