任务:模拟检查点技术实现数据库故障恢复
环境建立:
1。日志文件[my.log]记录
日志记录数据库操作格式:
事务名,操作,数据字段,原值,新值
故障发生时,通过解析日志记录进行故障恢复。
[my.log]日志文件
CHECKPOINT,1 #检查点1
T1,START
T2,START
T3,START
T1,UPDATE,A,400,500
T2,UPDATE,B,500,360
T3,UPDATE,C,600,700
T1,COMMIT
CHECKPOINT,2 #检查点2
T4,START
T5,START
T2,UPDATE,B,360,720
T3,UPDATE,C,700,480
T4,UPDATE,B,720,1000
T5,UPDATE,D,300,150
T2,COMMIT
T5,UPDATE,D,150,900
T4,COMMIT
发生故障 #故障点
2)SQLITE3数据库test.db及需要恢复的数据表
.创建数据表test
create table test(
id integer primary key autoincrement,
sym char(5),
val char(10)
);
#数据表初始值
insert into test(sym,val) values('A','400');
insert into test(sym,val) values('B','500');
insert into test(sym,val) values('C','600');
insert into test(sym,val) values('D','300');
insert into test(sym,val) values('E','100');
insert into test(sym,val) values('F','200');
id,sym,val
1,A,400
2,B,500
3,C,600
4,D,300
5,E,100
6,F,200
#用脚本模拟事务执行对数据库的修改
update test set val = '500' where sym = 'A';
update test set val = '360' where sym = 'B';
update test set val = '700' where sym = 'C';
update test set val = '720' where sym = 'B';
update test set val = '480' where sym = 'C';
update test set val = '1000' where sym = 'B';
update test set val = '150' where sym = 'D';
update test set val = '900' where sym = 'D';
#发生故障时,数据库中的数据:
sqlite> select * from test;
1|A|500
2|B|1000
3|C|480
4|D|900
5|E|100
6|F|200
问题描述:系统意外停机,数据库没有破坏,试根据日志文件记录设计数据库恢复Python程序脚本自动进行数据库恢复。
# 程序脚本解析日志结果
所有事务Ts:{'T1','T2','T4','T3','T5'}
最近检查点nearCheckpoint:CHECKPOINT,2
已持久化事务PERSISTED:{'T1'}
需要重做事务REDOs:{'T2','T4'}
需要重做记录redoRecs:
[('T2','UPDATE','B','500','360'),('T2','UPDATE','B','360','720'),('T4','UPDATE','B','720','1000')]
需要撤销事务UNDOs:{'T3','T5'}
需要撤销记录undoRecs:
[('T3','UPDATE','C','600','700'),('T3','UPDATE','C','700','480'),('T5','UPDATE','D','300','150'),('T5','UPDATE','D','150','900')]
所有更新记录updateRecs:
[('T1','UPDATE','A','400','500'),('T2','UPDATE','B','500','360'),('T3','UPDATE','C','600','700'),('T2','UPDATE','B','360','720'),('T3','UPDATE','C','700','480'),('T4','UPDATE','B','720','1000'),('T5','UPDATE','D','300','150'),('T5','UPDATE','D','150','900')]
@ 模拟事务更新数据库:{'A': '500', 'B': '1000', 'C': '480', 'D': '900'}
@ 未提交事务撤销恢复旧值:{'D': '300', 'C': '600'}
@ 已提交事务重做恢复新值:{'B': '1000'}
# 数据库已恢复为正确状态
{'A': '500', 'B': '1000', 'C': '600', 'D': '300'}
# Python脚本
# -*- coding: utf-8 -*-
"""
Created on Sun Oct 28 17:27:29 2018
@title: 日志操作db类
@author: 大卫fang
"""
from db import DB
import sys
# 创建测试数据环境testDB及test表
dbname = 'testDB.db'
db = DB(dbname)
# 创建表SQL命令
initial = """数据初始值
id,sym,val
1,A,400
2,B,500
3,C,600
4,D,300
*5,E,100
*6,F,200
"""
sql_select_master = "select name from sqlite_master where name='test'"
sql_delete_test = "delete from test"
sql_create_table = """
--创建测试表test
create table if not exists test(
id integer primary key autoincrement,
sym char(5),
val char(10)
);
"""
# 如果test表存在则清空,不存在则创建
if db.select(sql_select_master):
db.cur.execute(sql_delete_test)
db.con.commit()
else:
db.cur.execute(sql_create_table)
#input('# test表已重置,press any key to continue..')
# 数据初始化
sql_initial_value = """
-- 设置数据表初始值
insert into test(sym,val) values('A','400');
insert into test(sym,val) values('B','500');
insert into test(sym,val) values('C','600');
insert into test(sym,val) values('D','300');
--insert into test(sym,val) values('E','100');
--insert into test(sym,val) values('F','200');
"""
db.cur.executescript(sql_initial_value)
print(initial)
input('# 测试数据初始化,press any key to continue..')
# 解析日志
logfile = 'my.log'
db.logParsing(logfile)
input('# 日志已解析,press any key to continue..')
db.update()
input('# 事务数据已更新,press any key to continue..')
db.undo()
input('# 撤销数据已恢复,press any key to continue..')
db.redo()
print('# 重做数据已恢复...')
print('# 数据库已恢复!')
db.close()




