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   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. Use **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 a corrupted RDB store.
166
167Two backup modes are available: manual backup and automatic backup. Automatic backup is available only for system applications.
168
169### Manual Backup
170
171Use [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     store.executeSql('CREATE TABLE IF NOT EXISTS EMPLOYEE (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, AGE INTEGER, SALARY REAL, CODES BLOB)', (err) => {
194     })
195     console.info('Succeeded in getting RdbStore.');
196
197     // 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.
198     (store as relationalStore.RdbStore).backup("Backup.db", (err: BusinessError) => {
199       if (err) {
200         console.error(`Failed to backup RdbStore. Code:${err.code}, message:${err.message}`);
201           return;
202        }
203        console.info(`Succeeded in backing up RdbStore.`);
204     })
205   })
206   ```
207
208<!--Del-->
209
210### Automatic Backup (for System Applications Only)
211
212To 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:
213
214   ```ts
215   // Set haMode to MAIN_REPLICA.
216   const AUTO_BACKUP_CONFIG :relationalStore.StoreConfig = {
217     name: "BackupResotreTest.db",
218     securityLevel: relationalStore.SecurityLevel.S3,
219     haMode: relationalStore.HAMode.MAIN_REPLICA, // Data is written to the main and replica stores on a real-time basis.
220     allowRebuild: true
221   }
222
223   // Use getRdbStore() to create an RDB store instance.
224   relationalStore.getRdbStore(context, AUTO_BACKUP_CONFIG, (err, store) => {
225     if (err) {
226       console.error(`Failed to get RdbStore. Code:${err.code}, message:${err.message}`);
227       return;
228     }
229     console.info('Succeeded in getting RdbStore.');
230   })
231   ```
232
233<!--DelEnd-->
234
235## Rebuilding an RDB Store
236
237If 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.
238
239To 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).
240
241If **allowRebuild** in **StoreConfig** is set to **true** before the database is corrupted, the database will be automatically rebuilt when corrupted.
242
243If **allowRebuild** in **StoreConfig** is not set or is set to **false**, set **allowRebuild** to **true** and open the rebuilt RDB store. <br>Example:
244
245   ```ts
246   import { relationalStore } from '@kit.ArkData';
247   import { BusinessError } from '@kit.BasicServicesKit';
248
249   let store: relationalStore.RdbStore | undefined = undefined;
250
251   let context = getContext(this);
252
253   const STORE_CONFIG: relationalStore.StoreConfig = {
254     name: 'RdbTest.db',
255     securityLevel: relationalStore.SecurityLevel.S3,
256     allowRebuild: true
257   };
258   relationalStore.getRdbStore(context, STORE_CONFIG, (err, rdbStore) => {
259     store = rdbStore;
260     if (err) {
261       console.error(`Failed to get RdbStore. Code:${err.code},message:${err.message}`);
262       return;
263     }
264     store.executeSql('CREATE TABLE IF NOT EXISTS EMPLOYEE (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, AGE INTEGER, SALARY REAL, CODES BLOB)', (err) => {
265     })
266     console.info('Succeeded in getting RdbStore.');
267   })
268   ```
269
270## Restoring RDB Store Data
271
272If an RDB store is corrupted, you can restore it by using the database backup.
273
274You can restore data from either the manual backup data or automatic backup data. The latter is available only for system applications.
275
276### Restoring from Manual Backup Data
277
278You can use **backup()** to [perform manual backup](#manual-backup) and use **restore()** to restore data from the manual backup data.
279
280The 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.
281
2821. Throw an exception that indicates database corruption.
283
284   ```ts
285   let predicates = new relationalStore.RdbPredicates("EMPLOYEE");
286   if (store != undefined) {
287     (store as relationalStore.RdbStore).query(predicates, ["ID", "NAME", "AGE", "SALARY", "CODES"]).then((result: relationalStore.ResultSet) => {
288       let resultSet = result;
289       try {
290         /* ...
291            Logic for adding, deleting, and modifying data.
292            ...
293         */
294         // Throw an exception.
295         if (resultSet?.rowCount == -1) {
296           resultSet ?.isColumnNull(0);
297         }
298         // Call other APIs such as resultSet.goToFirstRow() and resultSet.count(), which also throw exceptions.
299         while (resultSet.goToNextRow()) {
300           console.info(JSON.stringify(resultSet.getRow()))
301         }
302         resultSet.close();
303       } catch (err) {
304           if (err.code === 14800011) {
305              // Perform step 2 (close result sets and then restore data).
306           }
307           console.error(JSON.stringify(err));
308       }
309     })
310   }
311   ```
312
3132. Close all opened result sets.
314
315   ```ts
316   // Obtain all opened result sets.
317   let resultSets: Array<relationalStore.ResultSet> = [];
318   // Call resultSet.close() to close all opened result sets.
319   for (let resultSet of resultSets) {
320     try {
321       resultSet.close();
322     } catch (e) {
323         if (e.code !== 14800014) {
324           console.error(`Code:${e.code}, message:${e.message}`);
325         }
326     }
327   }
328   ```
329
3303. Call **restore()** to restore data.
331
332   ```ts
333   try {
334     let context = getContext();
335     // 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.
336     let backup = context.databaseDir + '/backup/test_backup.db';
337     if(!fileIo.access(backup)) {
338       console.info("no backup file");
339       try {
340         (store as relationalStore.RdbStore).close;
341         store = undefined;
342       } catch (e) {
343           if (e.code != 14800014) {
344             console.info(JSON.stringify(e));
345           }
346       }
347       let storeConfig: relationalStore.StoreConfig = {
348         name: "BackupResotreTest.db",
349         securityLevel: relationalStore.SecurityLevel.S3,
350         allowRebuild: true
351       }
352       // Open the rebuilt RDB store and create tables.
353       // Generate data.
354       return
355     }
356     // Call restore() to restore data.
357     (store as relationalStore.RdbStore).restore(backup);
358   } catch (e) {
359       console.error(`Code:${e.code}, message:${e.message}`);
360   }
361   ```
362
363<!--Del-->
364
365### Restoring from Automatic Backup Data (for System Applications Only)
366
367Use [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.
368
369The 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.
370
371   ```ts
372   if (store !== undefined) {
373     try {
374       // Add, delete, modify, and query data.
375     } catch (err) {
376         if (err.code == 14800011) {
377           // Obtain all opened result sets.
378           let resultSets: Array<relationalStore.ResultSet> = [];
379           // Call resultSet.close() to close all opened result sets.
380           for (let resultSet of resultSets) {
381             try {
382               resultSet.close();
383             } catch (e) {
384                 if (e.code !== 14800014) {
385                   console.info(`Code:${err.code}, message:${err.message}`);
386                 }
387             }
388           }
389
390           (store as relationalStore.RdbStore).restore("Backup.db", (err: BusinessError) => {
391             if (err) {
392               console.error(`Failed to restore RdbStore. Code:${err.code}, message:${err.message}`);
393               return;
394             }
395             console.info(`Succeeded in restoring RdbStore.`);
396           })
397         }
398         console.info(`Code:${err.code}, message:${err.message}`);
399     }
400   }
401   ```
402
403<!--DelEnd-->
404