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