您的位置:首页 > 博客中心 > 数据库 >

关于数据库的DML操作注意事项

时间:2022-03-15 04:33

前言

  前些天要导入一些车商的初始化数据,发生了一件比较重大的数据错误,后面发现是sql写错了,导致整个数据表被update掉,当然数据量还不是很大,恢复了两个多小时,就把问题解决了。 但是这个事情让我考虑了很久,毕竟入行这么多年,还没有出现过这样的失误。下面就是我要介绍的几点方案,可以避免上述事情发生。

 正文     

一、首先我觉得框架的持久层对于DML的操作缺乏一定的校验,在安全性上是有问题的。

eg:   update  tb_01 set a =xx,b==xxx where 1=1;

   update  tb_01 set a =xx,b==xxx;

       update  tb_01 set a =xx,b==xxx where a and b;

类似于这样的SQL是缺乏校验的。,这是在开源中国上面看的解决mybaits中防止批量更新做的拦截器。我们目前用的rose框架,通过查看rose的源代码,在Rose(SystemInterpreter)类中也可以加入相应的校验拦截器,校验拦截器包括以下几点:

(1)update语句中时候存在WHERE关键字,若不存在,则不会更新,并且抛出异常。

 (2)update语句中存在WHERE关键字,若存在,则检查是否存在(=,<>,!==)等符号,若存在,则继续,若不存在,是否存在(like、in not in 、exist、not exist)等关键字,当然not in或者not exist可以不包含,若存在,则继续,否则不会更新,并且抛出异常。

这样可以防止批量更新的问题。

二、以前的时候觉得一个update语句其实没有必要有返回值,其实经历了这件事后,我觉得这个是一个比较好的编码行为,如果你更新的数据和你预期的数据不一致,那证明你错了或者你写的SQL错了,这就可以有效的防止这种批量更新的问题产生。

int count=update tb_02 set a=xxx where b=xx;

if(count!=1){

throw new SQLException("您所更新的数据影响0行,请注意查看");

}

上述是伪代码。但是意思是显而易见的。我们预知该SQL只能更新成功一条记录,有其他记录都是错误的。当然上面还有一个解决方案就是可以参照mybaits中校验的案例,设置主键注解,在DML 操作中,这是可以防止批量更新产生的数据问题。

当然有时候我们更新的数据也不是只有一行,有可能是多行,而且是无法预料的。这个时候我们可以使用两种方案进行处理

1)使用触发器的方式进行处理:

 在数据库中设置相应DML操作的触发器,每次做DML操作时,查询总数和当前数据影响的总数作比较。

弊端:使用SQL脚本进行批处理时可能会受到影响,DML的性能可能会收影响,但是基本上不是特别大,可以忽略不计。

2)在进行DML操作之前,首先查询总数,然后进行DML操作,然后返回值和总数进行比较

        弊端 :性能可能受影响,但是如果是特别重要的数据,我觉得这时候性能问题基本可以忽略不计。

三、其实这也是个人习惯问题,每次的sql写完了以后,需要检查,在开发环境进行测试。这是必要的步骤,但是有时候时间比较急,你可能会忘记这个步骤,觉得一定没问题,上线就是致命的。

四、比较重要的数据,我们可以做一些审计日志,这也是必要的,对于数据的流向和数据恢复等都有迹可循,对于数据恢复有比较大的好处。当然审计日志可以使用异步的并发框架或者消息队列去处理。

五、当然在上线的时候,数据的备份这是很有必要的,上线前需要备份数据库,上线过程中存在修复难度比较大的问题,可以做到数据回退,减少损失。

弊端:数据备份有可能存在数据延迟的现象,如果数据回退的话,有可能存在数据丢失。

总结

  上述提到的解决方案从持久层框架的改进、到程序员基本的一些良好习惯的养成、审计日志、还有数据备份等多个方面防止DML操作中防止批量更新引起的数据问题。DML主要包括(delete,update)操作。

其实对于我们来说,互联网就是玩数据,数据就是一切的根本,也是一切的来源,所以数据的安全性和有效性就显得特别重要。

热门排行

今日推荐

热门手游