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