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