首页 > 数据库 >分析mybatis的#{}、${}(#绑定变量超过一定值导致Oracle挂掉)

分析mybatis的#{}、${}(#绑定变量超过一定值导致Oracle挂掉)

时间:2022-09-20 18:34:46浏览次数:84  
标签:变量 item 绑定 挂掉 System mybatis Oracle

我后来改成了1万条,数据库相对小点 压力不大,也不会出现重启的问题;

 

最近跟数据库干上了
先说下问题起源,算奖确认订单,需要批量update订单,查了相关资料,是mybatis一次性绑定变量超过65535(这个数值并不准,因为后来绑定变量超过一万一又导致Oracle挂掉一次),引发了Oracle的一个bug,导致数据库宕机

mybatis 引入参数#和$区别
1.#是绑定变量的形式,底层会用#{}会被替换为?号,有参数映射,会在DefaultParameterHandler中进行设置占位符的操作;当使用$的时候,{value}是直接被替换为了对应的值,没有参数映射,不会进行设置占位符的操作

2.$不安全,可以被sql注入(使用时注意),#相对安全

测试
用批 量 更 新 没 有 绑 定 变 量 的 问 题 , 但 是 这 种 写 法 由 于 是 直 接 替 换 参 数 , 有 安 全 风 险 , 需 要 注 意 的 是 ; 批量更新没有绑定变量的问题,但是这种写法由于是直接替换参数,有安全风险,需要注意的是;批量更新没有绑定变量的问题,但是这种写法由于是直接替换参数,有安全风险,需要注意的是;{}这种取值方式,字符串类型需要加单引号

<update id="updateTable">
<foreach collection="params" item="item" index="index" open="begin" close=" ; end ;" separator=";">
update table
<set>
win_detail=${item.winDetail},
declaration=${item.declaration},
currency_Id=${item.currencyId},
activity_Type=${item.activityType}
</set>
where id=${item.id}
</foreach>
</update>
1
2
3
4
5
6
7
8
9
10
11
12
而用#这种写法,是绑定变量的,批量更新,一次性更新绑定变量超过一定数值就会有问题(可以批次更新数量少一些,如果数据量庞大,可以用多线程去跑),Oracle数据库即使打了补丁不会导致直接宕机,也会直接抛错执行不成功,这种用法一定要注意批次更新绑定变量数量,切记,切记!!!

<update id="updateTable">
<foreach collection="params" item="item" index="index" open="begin" close=" ; end ;" separator=";">
update table
<set>
win_detail=#{item.winDetail},
declaration=#{item.declaration},
currency_Id=#{item.currencyId},
activity_Type=#{item.activityType}
</set>
where id=#{item.id}
</foreach>
</update>
1
2
3
4
5
6
7
8
9
10
11
12
用上面这种方式,单线程跑15000条以上数据,数据库必挂,换一下思路,分批处理,一次处理500条,用多线程去跑,没问题

@Test
public void testBatch(){
List<ParamTest> testList = new ArrayList<ParamTest>();
List<AwardLotteryVO> ltList = awardMapper.getLtList();

for(AwardLotteryVO vo : ltList){
ParamTest t = new ParamTest();
t.setActivityType("1");
t.setCurrencyId(-1L);
t.setDeclaration("我必中");
t.setWinDetail("ok");
t.setBetId(vo.getBetId());
testList.add(t);
System.out.println(vo.getBetId());
}
Long start = System.currentTimeMillis();
//切割list,一次处理500条数据
List<List<ParamTest>> splitList = AwardUtils.splitList(testList, 500);
for(int i = 0; i < splitList.size(); i ++){
List<ParamTest> list = splitList.get(i);
System.out.println("执行第 " + i + " 次");
ThreadPool.putThread(new AwardConfirmTest(awardMapper, list));
}
System.out.println("----------end-----------------" + (System.currentTimeMillis() - start));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
以后工作或学习中,在使用相关工具、相关框架时还是需要弄清楚工具或者框架的工作原理,不断学习,才能游刃有余,临危不乱~

问题解决多亏了这两篇博客,Oracle实例重启事故分析 & 关于Mybatis的$和#,你真的知道他们的细节吗?
链接如下:
https://www.jianshu.com/p/f70d8bbee075
https://www.jianshu.com/p/d0fc693fc888
————————————————
参考:分析mybatis的#{}、${}(#绑定变量超过一定值导致Oracle挂掉)

标签:变量,item,绑定,挂掉,System,mybatis,Oracle
From: https://www.cnblogs.com/aspirant/p/16712068.html

相关文章

  • oracle导出csv文件后导入mysql
    场景:oracle数据库中有与mysql同名表,需要将oracle表数据导入mysql,需要手工操作工具:navicatpremium解决方案:1、使用plsql工具从oracle导出csv文件2、使用navicat工具......
  • MyBatis返回Map键值对数据Key值大小写问题
    Controller@RestController@RequestMapping("/web")publicclassMapKeyTest{@AutowiredprivateInvoicingBuyOrderServiceinvoicingBuyOrderService;......
  • Mybatis if标签判断数字大小
    if标签语法<select...>SQL语句1<iftest="条件表达式">SQL语句2</if></select>条件表达式中大于号小于号用gt,lt<iftest="numgt0">...</if><if......
  • oracle杀死存储过程的死锁
    杀死存储过程死锁:下面语句依次执行:```SELECTSIDASSID1FROMV$ACCESSWHEREOBJECT='GZ_JOB_RABBIT';SELECTSIDASSID2,SERIAL#,PADDRFROMV$SESSIONWHERESID=S......
  • Mybatis-plus 数据安全保护
    1、加密前 application-dev.ymlspring:datasource:url:jdbc:p6spy:mysql://localhost:3306/mybatis_plus?useUnicode=true&characterEncoding=utf-8&serverTim......
  • 05.有关MyBatis的配置与使用
    有关MyBatis的配置与使用虽然SpringDataJPA在国外广泛流行,但是在国内仍是MyBatis使用更加普遍整合MyBatis第一步:新建SpringBoot项目,在pom.xml中引入MyBatis的Starter......
  • MyBatisPlus-范围查询、模糊查询及排序查询
    MyBatisPlus-范围查询、模糊查询及排序查询原文链接:https://blog.csdn.net/m0_61961937/article/details/125967684一、范围查询二、模糊查询三、排序查询一、范围查......
  • Linux操作系统中查询Oracle数据库版本号
    操作步骤两种方式:----在Linux系统桌面上操作(1)若在Linux系统桌面上操作,使用快捷键【ctrl+alt+t】打开Linux终端命令行模式;(2)在Linux终端命令行中输入sqlplus命令进入Oracl......
  • Mybatis plus 查询
    1、子查询//管理主管查询IntegermanageSupervisor=query.getManageSupervisor();if(manageSupervisor!=null){......
  • Oracle元数据查询总结
     selectDISTINCT(OWNER)fromall_tablesselectTABLE_NAMEfromall_tableswhereOWNER='WZZLSDB'selectA.OWNER,A.TABLE_NAME,A.NUM_ROWS,A.NUM_ROWS*A.......