功能介绍
数据找回,又名数据闪回,误删除回滚,误操作回滚,数据重做…
解决的问题
数据库里的数据被误删除/更新,需要定位修改的SQL语句,影响范围,回滚误操作,此时怎么办?
- 方法1: DBA用前一天的数据库备份还原出来,然后找到更新前的SQL(这个通常需要花费几个小时的时间)
- 方法2: 如果发现误操作的时间比较及时,一般7天以内,可以通过解析数据库日志(MySQL的binlog,Oracle的archivelog)比较快速的找到误操作的SQL及时回滚
两个方法,都需要DBA参与
方法 | 依赖文件 | 可恢复范围 | 操作用时 |
---|---|---|---|
方法一 | 全备 | 1个月内 | 1-5小时 |
方法二 | 日志 | 7天 | 0.5小时 |
其中方法2,需要DBA找到并登录目标服务器,解析数据库日志,其中有研发和DBA的沟通时间,手动处理时间,我们可以通过自动化流程,让研发人员自助填写需求,在dba审批通过后系统自动执行.
自动化流程的作用
- 1.提高工作效率,不再需要DBA手动去查日志,解析日志… 将原先几十分钟的工作,变成自动化
- 2.减少误操作,减少手动处理问题时的手滑,操作命令写错了的运维风险
- 3.减少沟通成本,自助化服务无需(dba和研发)反复沟通细节
- 4.一般发现有数据更新错了,需要很快的得到响应,自助化流程可以减少非工作时间联系DBA的响应时长
- 5.便于统计哪些项目成员或业务线出现这种误更新的失误.
功能预览
设计了以下的表单填写页面,用于收集信息
设计了两步审批
- 负责人审批: 如果该库有具体的DB负责人,则DB负责人审批.否则由提交申请的用户上级审批
- DBA审批:DBA审批时会看到将要自动化执行的命令,并且可以在执行前修改部分参数.(通常默认的命令是最优的)
后端执行
- 执行是异步的.执行过程中会展示运行日志
- 执行完成后,会展示以下三块内容
- 1.后台运行日志 (用于DBA排查自动化任务时是否有异常)
- 2.SQL内容概览 (展示符合条件的表共有多少次ins/upd/del操作. 用于验证是否符合预期,该概览目前只支持MySQL,Oracle的还没实现)
- 3.解析出来的SQL文件 (最重要的部分)
代码实现
step1:表单代码
<step id="1" name="数据找回" displaytype="input">
<form>
<input name="dbid" title="选择数据库" inputtype="select_group" desc="" defaultvalue="" >
<style>
<div-class>span24</div-class><input-class>input-normal,input-small,input-normal,input-normal</input-class>
<connstr>link:db_monitor</connstr>
<sqlstr>
select b.dbid,
a.linktype as '库类型',
case a.appuse
when 9 then '线上'
when 4 then '验证'
when 3 then '测试'
when 1 then '开发'
end as '环境',
concat(a.linkname,'(',a.on_group,')') as '实例',
b.dbname as '库名'
from linkset a join linkdb b on a.linkname=b.linkname
where a.linktype in ('mysql','oracle')
order by a.linktype,a.appuse desc
</sqlstr>
</style>
</input>
<input name="tables" title="表名" inputtype="input" defaultvalue="*" desc="可为空,默认所有表的数据">
<style>
<div-class>span12</div-class><input-class>input-normal</input-class>
</style>
</input>
<input name="sqlmode" title="解析目的" inputtype="select" desc="" defaultvalue="redo">
<style>
<div-class>span12</div-class><input-class>input-normal</input-class>
<items text="查看SQL(redo)" value="redo" />
<items text="回滚SQL(undo)" value="undo" />
</style>
</input>
<input name="keywords" title="SQL关键字" inputtype="input" defaultvalue="" desc="可为空,指定SQL中必须出现的关键字">
<style>
<div-class>span12</div-class><input-class>input-normal</input-class>
</style>
</input>
<input name="starttime" title="StartTime" inputtype="datetime" desc="日志解析开始时间">
<style>
<div-class>span12</div-class><input-class>input-normal</input-class>
</style>
</input>
<input name="stoptime" title="StopTime" inputtype="datetime" desc="日志解析结束时间">
<style>
<div-class>span12</div-class><input-class>input-normal</input-class>
</style>
</input>
<input inputtype="lable" title="提示" value="用于误操作的历史数据找回,支持最远7天的历史数据找回,请尽量缩小精确时间范围段,避免长时间扫描日志造成资源占用任务失败" />
<btn id="tnok" title="提交解析申请" btnclass="button-warning" action="onclick_action" btntype = "button">
<action result="applyid" type="form_save">
</action>
<action type="dingding">
<touser>{step2owner}</touser>
<msgtype>markdown</msgtype>
<content>
<title>编号为{applyid}的{_formtitle}等待{step2owner}处理</title>
<text><![CDATA[
#### 编号为{applyid}的{_formtitle}等待{step2owner}处理
- 发起人:**{_username}**
- 集群:{linkname_display}
- 恢复目标:{dbname}.{tables}
- 时间:{starttime}-{stoptime}
- 进度:**0/3** 已提交申请
点击[查看流程进度]({dingdingstep1url})
]]></text></content>
</action>
</btn>
</form>
</step>
step2:负责人审批
<step id="2" name="负责人审核" displaytype="input">
<form>
<input inputtype="lable" title="流程编号" value="{applyid}" />
<input inputtype="lable" title="环境" value="{linktype},{appuse_display}" />
<input inputtype="lable" title="集群" value="{linkname_display}:{connstr_display}" />
<input inputtype="lable" title="库名" value="{dbname}(dbid:{dbid})" />
<input inputtype="lable" title="表名" value="{tables}" />
<input inputtype="lable" title="解析方式" value="{sqlmode}" />
<input inputtype="lable" title="SQL关键字" value="{keywords}" />
<input inputtype="lable" title="StartTime" value="{starttime}" />
<input inputtype="lable" title="StopTime" value="{stoptime}" />
<input inputtype="lable" title="提示" value="{tips}" />
<btn id="tnok" title="确认信息,通过审核" btnclass="button-success" action="onclick_action" btntype = "button" displayuser="{step2owner}">
<action result="tips" type="data_history_pre">
<dbid>{dbid}</dbid>
<applyid>{applyid}</applyid>
<tablename>{tables}</tablename>
<begintime>{starttime}</begintime>
<endtime>{stoptime}</endtime>
<keyword>{keywords}</keyword>
</action>
<action type="dingding">
<touser>@dba</touser>
<msgtype>markdown</msgtype>
<content>
<title>编号为{applyid}的{_formtitle}等待DBA处理</title>
<text><![CDATA[
#### 编号为{applyid}的{_formtitle}等待DBA处理
- 发起人:**{adduser}**
- 集群:{linkname_display}
- 恢复目标:{dbname}.{tables}
- 时间:{starttime}-{stoptime}
- 进度:**1/3** 负责人已审批
点击[查看流程进度]({dingdingstep1url})
]]></text></content>
</action>
</btn>
<btn id="tnno" title="取消申请" btnclass="button-warning" action="onclick_action" btntype = "button" displayuser="{adduser}">
<action type="dingding">
<touser>{step2owner}</touser>
<msgtype>markdown</msgtype>
<content>
<title>编号为{applyid}的{_formtitle}已撤回</title>
<text><![CDATA[
#### 编号为{applyid}的{_formtitle}已撤回<
- 发起人:**{adduser}**
- 集群:{linkname_display}
- 恢复目标:{dbname}.{tables}
- 时间:{starttime}-{stoptime}
- 进度:已撤回
点击[查看流程进度]({dingdingstep1url})
]]></text></content>
</action>
</btn>
</form>
</step>
step3:DBA审批
<step id="3" name="DBA确认" displaytype="input">
<form>
<input inputtype="lable" title="流程编号" value="{applyid}" />
<input inputtype="lable" title="环境" value="{linktype},{appuse_display}" />
<input inputtype="lable" title="集群" value="{linkname_display}:{connstr_display}" />
<input inputtype="lable" title="库名" value="{dbname}(dbid:{dbid})" />
<input inputtype="lable" title="表名" value="{tables}" />
<input inputtype="lable" title="解析方式" value="{sqlmode}" />
<input inputtype="lable" title="SQL关键字" value="{keywords}" />
<input inputtype="lable" title="StartTime" value="{starttime}" />
<input inputtype="lable" title="StopTime" value="{stoptime}" />
<input inputtype="lable" title="审批人" value="{step2owner}({step2time})" />
<input name="commandstr" title="要执行的命令" inputtype="input" defaultvalue="{commandstr}" desc="可修改">
<style>
<div-class>span24</div-class><input-class>input-big</input-class>
</style>
</input>
<input inputtype="lable" title="提示" value="{step_check_result}" />
<btn id="tnok" title="DBA确认" btnclass="button-success" action="onclick_action" btntype = "button" displayuser="@dba">
<action result="tips" type="data_history">
<dbid>{dbid}</dbid>
<applyid>{applyid}</applyid>
<commandstr>{commandstr}</commandstr>
<nextstep>5</nextstep>
</action>
<action type="dingding">
<touser>{adduser}</touser>
<msgtype>markdown</msgtype>
<content>
<title>编号为{applyid}的{_formtitle}已完成审批</title>
<text><![CDATA[
#### 编号为{applyid}的{_formtitle}已完成审批
- 发起人:**{addusr}**
- 集群:{linkname_display}
- 恢复目标:{dbname}.{tables}
- 时间:{starttime}-{stoptime}
- 进度:**2/3** 正在执行
点击[查看流程进度]({dingdingurl})
]]></text></content>
</action>
</btn>
<btn id="tnno" title="DBA拒绝" btnclass="button-warning" action="onclick_action" btntype = "button" displayuser="@dba">
<action type="jumpurl" url="apply.html?id={applyid}" title="提交成功."></action>
</btn>
</form>
</step>
step4:运行中
<step id="4" name="执行中" displaytype="input">
<form>
<input inputtype="lable" title="流程编号" value="{applyid}" />
<input inputtype="lable" title="环境" value="{linktype},{appuse_display}" />
<input inputtype="lable" title="集群" value="{linkname_display}:{connstr_display}" />
<input inputtype="lable" title="库名" value="{dbname}(dbid:{dbid})" />
<input inputtype="lable" title="表名" value="{tables}" />
<input inputtype="lable" title="SQL关键字" value="{keywords}" />
<input inputtype="lable" title="StartTime" value="{starttime}" />
<input inputtype="lable" title="StopTime" value="{stoptime}" />
<input inputtype="lable" title="审批人" value="{step2owner}({step2time})" />
<input inputtype="lable" title="执行命令" value="{commandstr}" />
<input inputtype="div" title="运行结果" value="{command_exec_log}" />
</form>
</step>
step5:执行结果展示
<step id="5" name="完成" displaytype="input">
<form>
<input inputtype="lable" title="流程编号" value="{applyid}" />
<input inputtype="lable" title="环境" value="{linktype},{appuse_display}" />
<input inputtype="lable" title="集群" value="{linkname_display}:{connstr_display}" />
<input inputtype="lable" title="库名" value="{dbname}(dbid:{dbid})" />
<input inputtype="lable" title="表名" value="{tables}" />
<input inputtype="lable" title="SQL关键字" value="{keywords}" />
<input inputtype="lable" title="StartTime" value="{starttime}" />
<input inputtype="lable" title="StopTime" value="{stoptime}" />
<input inputtype="lable" title="审批人" value="{step2owner}({step2time})" />
<input inputtype="lable" title="执行命令" value="{commandstr}" />
<input inputtype="div" title="运行结果" value="{command_exec_log}" />
</form>
</step>
以上,就是实现这个自动化流程的全部代码,采有xml设计.在Dboop平台上配置和运行.对公司研发部门同事开放申请流程.符合条件的同事可以自助式的完成数据找回需求.
小结
- 以上就是我们做数据找回自动化流程的思路和代码实现
- 通过配置自动化流程,一次配置,终身享受,极大的提升了DBA的工作效率和幸福指数
- Oracle部分跟MySQL的原理类似,共用了一个流程,但底层执行的命令不同,Oracle这里用到了OGG,回头单写一篇