• 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. Use **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. Use **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. Use **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. Use **restore()** to restore the KV store.
131
132   ```ts
133   let backupFile = 'BK001';
134   try {
135     kvStore.restore(backupFile, (err) => {
136       if (err) {
137         console.error(`Fail to restore data. Code:${err.code},message:${err.message}`);
138       } else {
139         console.info('Succeeded in restoring data.');
140       }
141     });
142   } catch (e) {
143     let error = e as BusinessError;
144     console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);
145   }
146   ```
147
1486. Use **deleteBackup()** to delete the backup file to release storage space.
149
150   ```ts
151   let files = ['BK001'];
152   try {
153     kvStore.deleteBackup(files).then((data) => {
154       console.info(`Succeed in deleting Backup. Data:filename is ${data[0]},result is ${data[1]}.`);
155     }).catch((err: BusinessError) => {
156       console.error(`Fail to delete Backup. Code:${err.code},message:${err.message}`);
157     })
158   } catch (e) {
159     let error = e as BusinessError;
160     console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);
161   }
162   ```
163
164## Backing Up an RDB Store
165
166A database backup can be used to quickly restore a corrupted RDB store.
167
168Two backup modes are available: manual backup and automatic backup. Automatic backup is available only for system applications.
169
170### Manual Backup
171
172Use [backup()](../reference/apis-arkdata/js-apis-data-relationalStore.md#backup) to manually back up an RDB store. <br>Example:
173
174   ```ts
175   import { relationalStore } from '@kit.ArkData';
176   import { BusinessError } from '@kit.BasicServicesKit';
177   import { fileIo } from '@kit.CoreFileKit';
178
179   let store: relationalStore.RdbStore | undefined = undefined;
180
181   let context = getContext(this);
182
183   const STORE_CONFIG: relationalStore.StoreConfig = {
184     name: 'RdbTest.db',
185     securityLevel: relationalStore.SecurityLevel.S3,
186     allowRebuild: true
187   };
188   relationalStore.getRdbStore(context, STORE_CONFIG, (err, rdbStore) => {
189     store = rdbStore;
190     if (err) {
191       console.error(`Failed to get RdbStore. Code:${err.code},message:${err.message}`);
192       return;
193     }
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     console.info('Succeeded in getting RdbStore.');
197
198     // Backup.db indicates the name of the database backup file. By default, it is in the same directory as the RdbStore file. You can also specify the directory in the customDir + backup.db format.
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<!--Del-->
210
211### Automatic Backup (for System Applications Only)
212
213To 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:
214
215   ```ts
216   // Set haMode to MAIN_REPLICA.
217   const AUTO_BACKUP_CONFIG :relationalStore.StoreConfig = {
218     name: "BackupResotreTest.db",
219     securityLevel: relationalStore.SecurityLevel.S3,
220     haMode: relationalStore.HAMode.MAIN_REPLICA, // Data is written to the main and replica stores on a real-time basis.
221     allowRebuild: true
222   }
223
224   // Use getRdbStore() to create an RDB store instance.
225   relationalStore.getRdbStore(context, AUTO_BACKUP_CONFIG, (err, store) => {
226     if (err) {
227       console.error(`Failed to get RdbStore. Code:${err.code}, message:${err.message}`);
228       return;
229     }
230     console.info('Succeeded in getting RdbStore.');
231   })
232   ```
233
234<!--DelEnd-->
235
236## Rebuilding an RDB Store
237
238If error code 14800011 is reported during the creation or use of an RDB store, the database is corrupted. If this occurs, you can rebuild the RDB store and restore data from a backup.
239
240To enable automatic rebuild of an RDB store, set **allowRebuild** in [StoreConfig](../reference/apis-arkdata/js-apis-data-relationalStore.md#storeconfig) to **true**. 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).
241
242If **allowRebuild** in **StoreConfig** is set to **true** before the database is corrupted, the database will be automatically rebuilt when corrupted.
243
244If **allowRebuild** in **StoreConfig** is not set or is set to **false**, set **allowRebuild** to **true** and open the rebuilt RDB store. <br>Example:
245
246   ```ts
247   import { relationalStore } from '@kit.ArkData';
248   import { BusinessError } from '@kit.BasicServicesKit';
249
250   let store: relationalStore.RdbStore | undefined = undefined;
251
252   let context = getContext(this);
253
254   const STORE_CONFIG: relationalStore.StoreConfig = {
255     name: 'RdbTest.db',
256     securityLevel: relationalStore.SecurityLevel.S3,
257     allowRebuild: true
258   };
259   relationalStore.getRdbStore(context, STORE_CONFIG, (err, rdbStore) => {
260     store = rdbStore;
261     if (err) {
262       console.error(`Failed to get RdbStore. Code:${err.code},message:${err.message}`);
263       return;
264     }
265     store.executeSql('CREATE TABLE IF NOT EXISTS EMPLOYEE (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, AGE INTEGER, SALARY REAL, CODES BLOB)', (err) => {
266     })
267     console.info('Succeeded in getting RdbStore.');
268   })
269   ```
270
271## Restoring RDB Store Data
272
273If an RDB store is corrupted, you can restore it by using the database backup.
274
275You can restore data from either the manual backup data or automatic backup data. The latter is available only for system applications.
276
277### Restoring from Manual Backup Data
278
279You can use **backup()** to [perform manual backup](#manual-backup) and use **restore()** to restore data from the manual backup data.
280
281The 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.
282
2831. Throw an exception that indicates database corruption.
284
285   ```ts
286   let predicates = new relationalStore.RdbPredicates("EMPLOYEE");
287   if (store != undefined) {
288     (store as relationalStore.RdbStore).query(predicates, ["ID", "NAME", "AGE", "SALARY", "CODES"]).then((result: relationalStore.ResultSet) => {
289       let resultSet = result;
290       try {
291         /* ...
292            Logic for adding, deleting, and modifying data.
293            ...
294         */
295         // Throw an exception.
296         if (resultSet?.rowCount == -1) {
297           resultSet ?.isColumnNull(0);
298         }
299         // Call other APIs such as resultSet.goToFirstRow() and resultSet.count(), which also throw exceptions.
300         while (resultSet.goToNextRow()) {
301           console.info(JSON.stringify(resultSet.getRow()))
302         }
303         resultSet.close();
304       } catch (err) {
305           if (err.code === 14800011) {
306              // Perform step 2 (close result sets and then restore data).
307           }
308           console.error(JSON.stringify(err));
309       }
310     })
311   }
312   ```
313
3142. Close all opened result sets.
315
316   ```ts
317   // Obtain all opened result sets.
318   let resultSets: Array<relationalStore.ResultSet> = [];
319   // Call resultSet.close() to close all opened result sets.
320   for (let resultSet of resultSets) {
321     try {
322       resultSet.close();
323     } catch (e) {
324         if (e.code !== 14800014) {
325           console.error(`Code:${e.code}, message:${e.message}`);
326         }
327     }
328   }
329   ```
330
3313. Call **restore()** to restore data.
332
333   ```ts
334   try {
335     let context = getContext();
336     // Backup.db indicates the name of the database backup file. By default, it is in the same directory as the RdbStore file. You can also specify the directory in the customDir + backup.db format.
337     let backup = context.databaseDir + '/backup/test_backup.db';
338     if(!fileIo.access(backup)) {
339       console.info("no backup file");
340       try {
341         (store as relationalStore.RdbStore).close;
342         store = undefined;
343       } catch (e) {
344           if (e.code != 14800014) {
345             console.info(JSON.stringify(e));
346           }
347       }
348       let storeConfig: relationalStore.StoreConfig = {
349         name: "BackupResotreTest.db",
350         securityLevel: relationalStore.SecurityLevel.S3,
351         allowRebuild: true
352       }
353       // Open the rebuilt RDB store and create tables.
354       // Generate data.
355       return
356     }
357     // Call restore() to restore data.
358     (store as relationalStore.RdbStore).restore(backup);
359   } catch (e) {
360       console.error(`Code:${e.code}, message:${e.message}`);
361   }
362   ```
363
364<!--Del-->
365
366### Restoring from Automatic Backup Data (for System Applications Only)
367
368Use [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.
369
370The 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.
371
372   ```ts
373   if (store !== undefined) {
374     try {
375       // Add, delete, modify, and query data.
376     } catch (err) {
377         if (err.code == 14800011) {
378           // Obtain all opened result sets.
379           let resultSets: Array<relationalStore.ResultSet> = [];
380           // Call resultSet.close() to close all opened result sets.
381           for (let resultSet of resultSets) {
382             try {
383               resultSet.close();
384             } catch (e) {
385                 if (e.code !== 14800014) {
386                   console.info(`Code:${err.code}, message:${err.message}`);
387                 }
388             }
389           }
390
391           (store as relationalStore.RdbStore).restore("Backup.db", (err: BusinessError) => {
392             if (err) {
393               console.error(`Failed to restore RdbStore. Code:${err.code}, message:${err.message}`);
394               return;
395             }
396             console.info(`Succeeded in restoring RdbStore.`);
397           })
398         }
399         console.info(`Code:${err.code}, message:${err.message}`);
400     }
401   }
402   ```
403
404<!--DelEnd-->
405