将数据库恢复到一个之前的时间点的能力带来了一些复杂性,这和有关时间旅行和平行宇宙的科幻小说有些相似。例如,在数据库的最初历史中,假设周二晚上5:15时删除了一个关键表,但是一直到周三中午才意识到错误。这时,可以备份恢复到周二晚上5:14的时间点,并上线运行。在数据库宇宙的这个历史中,从没有丢弃该表。但是假设后来意识到这并非一个好主意,并且想回到最初历史中周三早上11:00。此时已经没法这样做,在数据库在线运行期间,重写了某些WAL段文件,而这些文件本来可以将数据库返回到用户希望回到的时间。因此,为了避免出现这种状况,用户需要将完成时间点恢复后生成的WAL记录序列与初始数据库历史中产生的WAL记录序列区分开来。
要解决这个问题,UXDB有一个时间线概念。无论何时当一次归档恢复完成,一个新的时间线被创建来标识恢复之后生成的WAL记录序列。时间线ID号是WAL段文件名的一部分,因此一个新的时间线不会重写由之前的时间线生成的WAL数据。实际上可以归档很多不同的时间线。虽然这可能看起来是一个无用的特性,但是它常常扮演救命稻草的角色。考虑到用户不太确定需要恢复到哪个时间点的情况,可能不得不做多次时间点恢复尝试,直到最终找到从旧历史中分支出去的最佳位置。如果没有时间线,该处理将会很快成为一堆不可管理的混乱。而有了时间线,可以恢复到任何之前的状态,包括早先被放弃的时间线分支中的状态。
每次当一个新的时间线被创建,UXDB会创建一个“时间线历史”文件,它显示了新时间线是什么时候从哪个时间线分支出来的。系统在从一个包含多个时间线的归档中恢复时,这些历史文件对于允许系统选取正确的WAL段文件非常必要。因此,和WAL段文件相似,它们也要被归档到WAL归档区域。历史文件是很小的文本文件,因此将它们无限期地保存起来的代价很小,而且也是很合适的(而段文件都很大)。为了清晰明了,用户可以在历史文件中增加注释来记录如何和为什么要创建该时间线。当由于试验的结果拥有了一大堆错综复杂的不同时间线时,这种注释将会特别有价值。
恢复的默认行为是沿着相同的时间线进行恢复,该时间线是基础备份创建时的当前时间线。如果希望恢复到某个子时间线(即,回到在一次恢复尝试后产生的某个状态),需要在uxsinodb.conf中指定目标时间线ID。不能恢复到早于该基础备份之前分支出的时间线。
上述时间线具体如下如所示:
第一次恢复:
解压基础备份:
tar -xvf backup.tar
配置uxsinodb.conf文件:
vi backup/uxsinodb.conf
restore_command = 'cp /mnt/server/archivedir/%f %p' //从归档目录恢复日志。 recovery_target_time = '2018-12-11 17:14:00 ' //指定归档时间点,若未指定则恢复到故障前的最后一个完成的事务。 recovery_target_timeline = 'latest' //指定归档时间线,‘latest’代表最新的时间线分支,如没指定恢复到故障前的ux_control中的时间线。
创建并配置标志文件standby.signal:
vi standby.signal
standby_mode = 'off' //打开后将会以备库身份启动,而不是即时恢复。
启动数据库:
uxsql
此时将会产生新的timeline,而且会生成一个新的history文件。
第二次恢复:
停止数据库,删除数据文件夹。
解压基础备份:
tar -xvf backup.tar
配置uxsinodb.conf文件:
vi backup/uxsinodb.conf
restore_command = 'cp /mnt/server/archivedir/%f %p' //从归档目录恢复日志。 recovery_target_time = '2018-12-12 11:00:00 ' //指定归档时间点,若未指定则恢复到故障前的最后一个完成的事务。 recovery_target_timeline = '1' //指定归档时间线,如没指定恢复到故障前的ux_control中的时间线
创建并配置标志文件standby.signal:
vi standby.signal
standby_mode = 'off' //打开后将会以备库身份启动,而不是即时恢复。
启动数据库:
uxsql
此时将再次产生新的timeline,而且会生成一个新的history文件。