oracle大数据量。表分区提示查询效率
案发现场
//防止全局配置了 所以这里定义sprnig 不托管事物
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public boolean deductNumber(Long id,int i){ DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);//设置事物传播行为
TransactionStatus status = null;
try {
//开启事物
status = transactionManager.getTransaction(def);
if(id==null){
return false;//库存编号不能为空
}
if(i<=0){
return false;//扣除库存不能小于0
}
//提交事务
transactionManager.commit(status);
} catch (Exception e) {
transactionManager.rollback(status);
return false;
}
return true;
}
导致问题
线上出现 订单下单 提示用户订单创建成功 但是订单不在了 对应的钱没扣 库存也没扣 看代码没有问题 日志也是正常打印 没抛错没回滚
mysql 部分表出现锁等待 单表操作无并发也出现锁等待
自己的坑自己填
1.day 1
怀疑是数据库的问题 事物提交了 但是数据库没持久 在下单操作打印了日志判断是否回滚并打印日志
if(status.isRollbackOnly()){
logger.info("======事物已回滚=========");
return false;
}
2.day 2
第二天又出现这种情况 同时发现伴随着后台有个事物一一直 在select * from information_schema.innodb_trx; runing 持续半个小时以上
但是发现丢单的地方======事物已回滚========
这个时候很疑惑 因为下单很多逻辑怀疑是某个方法设置了回滚状态但是抛出true 来log4j开启事物管理器debug日志
log4j.logger.org.springframework.jdbc.datasource.DataSourceTransactionManager=DEBUG
开启之后开启事物 设置事物状态合并事物都会打印对应的日志
同时为了定位到runing的事物是在哪个地方 在重写了log4j layout 打印了事物号和线程号
log4j配置log4j.appender.stdout.layout =com.chinayanghe.dms.log4jUtil.MyPatternLayout
public class MyPatternLayout extends PatternLayout {
/**
* 日志打印
*/
protected Logger logger = LoggerFactory.getLogger(getClass());
private static ThreadLocal<String> localTreadIds = new ThreadLocal<String>();
public static void removeTreadLocalCache() {
localTreadIds.remove();
}
@Override
public String format(LoggingEvent event) {
String logStr = super.format(event);
try {
if (logStr.indexOf("SELECT trx_id FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID()") < 0
&&logStr.indexOf("SELECT trx_mysql_thread_id FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID();")<0) {
//表示是sql打印尝试获得事物号
if (logStr.indexOf("[org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:145)] ==> Preparing:") >= 0) {
WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
String treadId = localTreadIds.get();
if (StringUtil.isEmpty(treadId)) {
JDBCTransactionInfoService jdbcTransactionInfoService = (JDBCTransactionInfoService) wac.getBean("jDBCTransactionInfoServiceImpl");
List<String> treadIds = jdbcTransactionInfoService.selectTrxMysqlThreadId();
if (CollectionUtils.isNotEmpty(treadIds)) {
treadId = treadIds.get(0);
localTreadIds.set(treadId);
}
}
if (treadId != null) {
logStr = logStr.replace("[DEBUG]", "[DEBUG][事务号" + treadId + "]");
}
} else if (logStr.indexOf("Transactional code has requested rollback") >= 0) {
logStr = logStr.replace("Transactional code has requested rollback", "Transactional code has requested rollback,线程id:" + Thread.currentThread().getId());
}
} else {
return "";
}
long treadId = Thread.currentThread().getId();
logStr = logStr.replace("[DEBUG]", "[DEBUG][线程id:" + Thread.currentThread().getId() + "]").replace("[INFO]", "[INFO][线程id:" + treadId + "]");
} catch (Exception e) {
logger.info(e.getMessage());
}
return logStr;
}
}
3.day3出现丢单根据日志发现 丢单的都是同一个线程id 事物号也相同 同时丢单的地方都没有开启事物日志而是事物已存在合并的日志
根据日志 一个一个看 发现规律 线程id最后一次打印 creating transaction 之后 再也没打印 然后定位到最后一次打印事物 的方法是手动开启事物的方法 有个地方忘记回滚 直接return了
这个时候反应过来 是这个方法没提交一直挂起 spring事物是基于线程缓存 tomcat会回收线程到线程池 下单分配到这个线程 因为手动开启事物还存在 所以公用同一个事物 事物一致挂起 当遇到RR模式锁等待抛出wai lock
statu的回滚状态会设置为true 所以才会出现我的下单日志打印都是回滚
优化代码
//防止全局配置了 所以这里定义sprnig 不托管事物
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public boolean deductNumber(Long id,int i){ DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);//设置事物传播行为
TransactionStatus status = null;
try {
//开启事物
status = transactionManager.getTransaction(def);
if(id==null){
transactionManager.rollback(status);
return false;//库存编号不能为空
}
if(i<=0){
return false;//扣除库存不能小于0
}
//提交事务
transactionManager.commit(status);
} catch (Exception e) {
transactionManager.rollback(status);
return false;
}finally {
//加上此代码 防止忘记
if(status!=null&&!status.isCompleted()){
transactionManager.rollback(status);
return false;
}
} return true;
}
总结原因:
事物一直没有被提交,事物状态是通过线程缓存实现的,当线程回收到线程池,后面再分分派的这个线程使用的同一个连接和事物,事物其实一直挂起
oracle大数据量。表分区提示查询效率的更多相关文章
- c#中@标志的作用 C#通过序列化实现深表复制 细说并发编程-TPL 大数据量下DataTable To List效率对比 【转载】C#工具类:实现文件操作File的工具类 异步多线程 Async .net 多线程 Thread ThreadPool Task .Net 反射学习
c#中@标志的作用 参考微软官方文档-特殊字符@,地址 https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/toke ...
- Oracle大数据量查询实际分析
Oracle数据库: 刚做一张5000万条数据的数据抽取,当前表同时还在继续insert操作,每分钟几百条数据. 该表按照时间,以月份为单位做的表分区,没有任何索引,当前共有14个字段,平均每个字段3 ...
- (转)SqlServer为大数据量表建索引
本文转载自:http://blog.csdn.net/iangujun/article/details/8136764 之前从没有用SqlServer数据库处理过大数据量的表,都是用Oracle,然后 ...
- 大数据量表中,增加一个NOT NULL的新列
这次,发布清洗列表功能,需要对数据库进行升级.MailingList表加个IfCleaning字段,所有的t_User*表加个IfCleaned字段. 脚本如下 对所有的t_User表执行 a ...
- 大数据量下DataTable To List效率对比
使用反射和动态生成代码两种方式(Reflect和Emit) 反射将DataTable转为List方法 public static List<T> ToListByReflect<T& ...
- oracle大数据量更新引发的死锁问题解决方法及oracle分区和存储过程的思考
前言 前几天上午在对数据库的一张表进行操作的时候,由于这张表是按照时间的一张统计表,正好到那天没有测试数据了,于是我想将表中所有的时间,统一更新到后一个月,于是对80w条数据的更新开始了.整个过程曲折 ...
- ORACLE中大数据量查询实现优化
大数据量查询,对数据库开发者来说,性能问题往往是最需要费尽心机的,借此总结自己优化此类问题的心得与大家分享,以免大家走更多的弯路. 1.使用主键临时表 大数据量表关联查询,是性能开销的主要原因.通过主 ...
- java大数据量调优
从总体上来看,对于大型网站,比如门户网站,在面对大量用户访问.高并发请求方面,基本的解决方案集中在这样几个环节:1.首先需要解决网络带宽和Web请求的高并发,需要合理的加大服务器和带宽的投入,并且需要 ...
- Oracle大数据常见优化查询
[转]http://www.cnblogs.com/myhappylife/p/5006774.html 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的 ...
随机推荐
- delphi附带通用控件安装方法:
附带通用控件安装方法:----------基本安装1.对于单个控件,Componet-->install component..-->PAS或DCU文件-->install;2.对于 ...
- SPM - data analysis
来源: SPM基本原理与使用PPT, 北师大,朱朝喆研究员,http://www.cnblogs.com/haore147/p/3633515.html ❤ First-level analysis: ...
- mybatis 3.2.7 与 spring mvc 3.x、logback整合
github上有一个Mybatis-Spring的项目,专门用于辅助完成mybatis与spring的整合,大大简化了整合难度,使用步骤: 准备工作: maven依赖项: <properties ...
- Spring 4.0.2 学习笔记(1) - 最基本的注入
1. 添加maven支持 <dependency> <groupId>org.springframework</groupId> <artifactId> ...
- 【福吧资源网整理】老男孩-python运维6期 不加密
老男孩-python运维6期 不加密,连夜整理出来分享给大家老男孩的python教程确实不错. 教程目录: 下载地址:http://www.fu83.cn/thread-204-1-1.html
- ubuntu 安装VmTool
VM tools 是Vmware的一组工具.主要用于虚拟主机显示优化与调整,另外还可以方便虚拟主机与本机的交互,如允许共享文件夹,甚至可以直接从本机向虚拟主机拖放文件.鼠标无缝切换.显示分辨率调整等, ...
- 你是否还在质疑EF的性能
1. 写在前面的话 一直没有写博客的习惯,感觉太浪费时间,没有那么多精力,其实仔细一想,写博客是一种习惯,也是一种心境,同时也是对自己所掌握的知识结构的一个梳理过程,对自己知识体系的一个巩固,同时也是 ...
- 深入理解计算机系统(1.2)---hello world的程序是如何运行的
在写本章的内容之前,LZ先做个小广告.其实也不算是什么广告,就是LZ为了和各位猿友交流方便,另外也确实有个别猿友留言或者在博客里发短消息给LZ要联系方式.因此LZ斗胆建立了一个有关<深入理解计算 ...
- [BZOJ 1997][HNOI2010]Planar(2-SAT)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1997 分析: 考虑每条边是在圈子里面还是圈子外面 所以就变成了2-SAT判定问题了= ...
- Xen
Xen是一个开放源代码虚拟机监视器,由剑桥大学开发.它打算在单个计算机上运行多达128个有完全功能的操作系统. 在旧(无虚拟硬件)的处理器上执行Xen,操作系统必须进行显式地修改(“移植”)以在Xen ...