zoukankan      html  css  js  c++  java
  • 从业务角度 减少代码执行的时间 和 因长时间执行的而带来的代码复杂性 日志恢复数据

    从日志提取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()


    今后,数据库中的时间戳字段应该交由业务代码处理,即再写入和更新对数据库的环节,服务降级,单一化,去计算化
    数据的计算功能,不应在业务的读写数据库阶段体现,而应在数据分析/数据挖掘环节体现。

  • 相关阅读:
    SQL-W3School-高级:SQL CHECK 约束
    SQL-W3School-高级:SQL FOREIGN KEY 约束
    SQL-W3School-高级:SQL PRIMARY KEY 约束
    SQL-W3School-高级:SQL UNIQUE 约束
    ylbtech-SQL-W3School-高级:SQL NOT NULL 约束
    SQL-W3School-高级:SQL 约束(Contraints)
    SQL-W3School-高级:SQL CREATE TABLE 语句
    SQL-W3Chool-高级:SQL CREATE DATABASE 语句
    SQL-W3School-高级:SQL SELECT INTO 语句
    02:输出最高分数的学生姓名
  • 原文地址:https://www.cnblogs.com/rsapaper/p/8204885.html
Copyright © 2011-2022 走看看