从业务角度 减少代码执行的时间 和 因长时间执行的而带来的代码复杂性 日志恢复数据
从日志提取sql恢复误删改数据
遍历log目录
[root@hadoop3 log]# history | grep grep | grep log
609 find / | grep access.log
1009 find . -type f | xargs grep INSERT INTO > /log_recover_insert.r
1011 find . -type f | xargs grep VALUES > /recover_insert.log
1013 find . -type f | xargs grep VALUES > /recover_insert.log
1015 find . -type f | xargs grep VALUES > /recover_insert.log
1017 find . -type f | xargs grep VALUES > /recover_insert.log
1019 find . -type f | xargs grep UPDATE > /recover_update.log
1023 history | grep grep | grep log
[root@hadoop3 log]#
注意 日志可能存在多个目录/节点服务器
初始脚本
import pymysql
insert_l = []
with open('recover_insert.log', 'r', encoding='utf-8') as f:
for i in f:
d = i
ii = '%s%s' % (i.split('INSERT INTO')[1].split('VALUES')[1].split('")')[0], '")')
ii = ii.replace('("', 'XLA').replace('","', 'XLB').replace('")', 'XLC').replace('"', ',').replace('XLA',
'("').replace(
'XLB', '","').replace('XLC', '")')
insert_l.append(ii)
conn = pymysql.connect(
host='192.168.2.210',
port=3306,
user='root',
passwd='nfwt&2016',
charset='utf8',
database='xl_test',
use_unicode=False
)
for i in insert_l:
cursor = conn.cursor()
try:
sql = '%s%s%s' % ('INSERT INTO order_temp (title,url,remarks,create_time,uid) VALUES ', i,';')
cursor.execute(sql)
conn.commit()
except Exception as e:
sql = '%s%s%s' % ('INSERT INTO order_temp (title,url,remarks,uid) VALUES ', i,';')
try:
cursor.execute(sql)
conn.commit()
except Exception as e1:
print('e1',e1)
conn.close()
执行时间已经大于半个小时
开始在局域网测试机写入数据库,再将整表导入线上服务器
出现问题 同事报告磁盘错误
数据无法写入
在查历史备份数据表大小
order_temp 在21号上午都419M了:预计截止到今天上午 不低于500M
局域网磁盘空间可以清文件或换服务器
但是预估500M的全表sql导入线上,主要受网速带宽制约
但如果将恢复代码直接写入线上数据库,则存在与其他业务的挤占连接数的影响和增大代码处理异常情况的复杂性
try try 层层异常嵌套
从业务角度考虑该问题:
order_temp表中的数据url再检测次数达标后,就转移至order_temp
而order数据表当前完整
没有业务的直接必要性恢复全表数据
OK- UPDATE order_temp SET no_open_times=no_open_times+1,remarks=CONCAT("_hostname_hadoop3_host_192.168.2.5120180101 09:10:38 os.getppid() 1746 os.getpid() 1763 threading.get_ident 139959621117696 start_time 20180101_054002huangnan.qd8.com.cn/qtshangwu/xinxi2_42023287.html,404,http://huangnan.qd8.com.cn/qtshangwu/xinxi2_42023287.html,<Response [404]>,Not Found",remarks),update_time="1514769054" WHERE url="huangnan.qd8.com.cn/qtshangwu/xinxi2_42023287.html" AND no_ad_times+no_open_times+ok_times<script_need_run_times ;
SET a=a+1,b=CONCAT('new',b)
数据更新错误
但是原更新代码,没有处理update_time字段,即原代码将更新时间戳的逻辑交给了数据库!导致直接从日志提取出的sql语句不能直接处理该字段,虽然通过日志的单条时间戳可以间接恢复
import pymysql
insert_l, insert_url_l = [], []
with open('recover_insert.log', 'r', encoding='utf-8') as f:
for i in f:
ii = '%s%s' % (i.split('INSERT INTO')[1].split('VALUES')[1].split('")')[0], '")')
ii = ii.replace('("', 'XLA').replace('","', 'XLB').replace('")', 'XLC').replace('"', ',').replace('XLA',
'("').replace(
'XLB', '","').replace('XLC', '")')
if '2018' not in ii:
continue
url = ii.split('","')[1]
insert_url_l.append(url)
insert_l.append(ii)
print(ii)
update_l = []
with open('recover_update.log', 'r', encoding='utf-8') as f:
for i in f:
ii = i.split('UPDATE')[1].split('[th')[0]
if '2018' not in ii:
continue
url = ii.split('url="')[1].split('"')[0]
if url not in insert_url_l:
continue
update_l.append(ii)
print(ii)
del f, insert_url_l
h, pt, u, pwd, db = '192.168.2.210', 3306, 'root', 'nfwt&2016', 'xl_product_DONOT_REMOVE'
conn = pymysql.connect(host=h, port=3306, user=u, passwd=pwd, charset='utf8', database=db)
cursor = conn.cursor()
for i in insert_l:
cursor = conn.cursor()
try:
sql = '%s%s%s' % ('INSERT INTO order_temp (title,url,remarks,create_time,uid) VALUES ', i, ';')
cursor.execute(sql)
conn.commit()
print('OK-4f', sql)
except Exception as e:
print(e, ' ', sql)
sql = '%s%s%s' % ('INSERT INTO order_temp (title,url,remarks,uid) VALUES ', i, ';')
try:
cursor.execute(sql)
conn.commit()
print('OK-3f', sql)
except Exception as e1:
print(e1, ' ', sql)
del insert_l
for i in update_l:
sql = '%s%s%s' % ('UPDATE', i, ';')
try:
cursor.execute(sql)
conn.commit()
print('OK-', sql)
except Exception as e2:
print(e2, ' ', sql)
conn.close()
今后,数据库中的时间戳字段应该交由业务代码处理,即再写入和更新对数据库的环节,服务降级,单一化,去计算化
数据的计算功能,不应在业务的读写数据库阶段体现,而应在数据分析/数据挖掘环节体现。