今天一位同事找我寻求帮助,售后向他反馈的问题不知道如何排查,他尝试分析服务器端日志文件, 但是日志文件中并没有报错信息,查询源码时候发现,报错信息被try...catch处理
顺便提一句, 排查问题时候需要记住一句话:“相信日志, 相信数据、相信代码, 不要相信售后的嘴”。
没有报错日志,那么就先分析源码。 通过现有业务功能和日志文件中仅有的操作日志, 定位问题在某个订单处理过程中,我们发现只有某个客户存在问题,其他客户正常,断定是数据问题,因此我尝试了解订单数据,以便了解客户办理的业务信息,在这个过程中发现了可疑点。
订单的详情内容XML 以CLOB方式存储, 在PLSQL中查看CLOB对象的时候, 发现存在错误提示,从信息看解析字符串异常
-
- Error: 无效的 unicode 字符。
- Line: (93)
- Text: <remark>remark>
- File:
查看订单内容信息,发现订单详情中缺失存在
- <createOperator>
- <version>0version>
- <mustBindTerminal>falsemustBindTerminal>
- <isVIPOperator>falseisVIPOperator>
- createOperator>
- <modifyOperator>
- <version>0version>
- <mustBindTerminal>falsemustBindTerminal>
- <isVIPOperator>falseisVIPOperator>
- modifyOperator>
- <remark>remark>
- <operationTerminal>
- <version>0version>
- operationTerminal>
- <operationSpot>
- <id>1484id>
- <version>0version>
- operationSpot>
- <version>0version>
- <code>000006816211code>
订单的详情内容在Oracle数据库中以CLOB方式存储。 什么时候CLOB呢?Oracle 存储字符串一般使用VARCHAR2 变量类型,当大于其最大字节长度时候(网络上很多人说最大字节长度为32767),需要使用大数据类型来存储,也可以叫大对象类型( Large Object)。CLOB类型的最大优势就是容量大,最多能容纳4GB的数据。
了解这些信息后, 尝试重现问题, 测试环境中找了1条类似的记录,将订单的对应字段修改为"�" , 程序中取消try..catch处理,复现了现场问题, 查看日志发发现,日志中明确显示了XML中存在字符"�" 造成解析XML错误
- Caused by: org.xml.sax.SAXParseException; lineNumber: 93; columnNumber: 24; Character reference "" is an invalid XML character.
- at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
- at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
- at com.thoughtworks.xstream.io.xml.DomDriver.createReader(DomDriver.java:108)
- ... 122 more
因为字符解析引发的问题, 因此通过replace函数将问题字符串替换为可解析的字符串即可
Replace() 函数是用另外一个值来替代串中的某个值
需要注意的是使用下面的SQL无法达到解决问题的效果
- update orderinfo o
- set o.ordercontent = replace(o.ordercontent,"", 'null')
- where o.orderid = 61926418
字符 "�"中的&会被oracle当做变量来处理,例如下面的SQL执行结果如下
- --测试
- select '' from dual;
执行结果:
为了解决此问题就需要用到Oralce的转义操作,在SQL语句中通过chr(38) 来替换字符&,参考SQL
- --测试
- select chr(38)||'#x0;' from dual;
执行结果:
�
最终使用以下方式解决问题
- update orderinfo o
- set o.ordercontent = replace(o.ordercontent, chr(38)||'#x0;', 'null')
- where o.orderid = 61926418
通过本次问题处理需要记住以下几点