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 涉及的 ...
随机推荐
- some basic graph theoretical measures
· mean characteristic path length calculated as the average length of the shortest path between two ...
- MySQL数据库的优化(上)单机MySQL数据库的优化
MySQL数据库的优化(上)单机MySQL数据库的优化 2011-03-08 08:49 抚琴煮酒 51CTO 字号:T | T 公司网站访问量越来越大,导致MySQL的压力越来越大,让我们自然想到的 ...
- 异常检测算法--Isolation Forest
南大周志华老师在2010年提出一个异常检测算法Isolation Forest,在工业界很实用,算法效果好,时间效率高,能有效处理高维数据和海量数据,这里对这个算法进行简要总结. iTree 提到森林 ...
- ASP.NET 系列:单元测试之SmtpClient
使用SmtpClient发送Email时,我们可以创建ISmtpClient接口和SmtpClientWrapper适配类,在单元测试中对ISmtpClient进行Mock或自定义FackeSmtpC ...
- sqlserver查询所有表名、字段名、类型、长度和存储过程、视图的创建语句
-- 获得存储过程创建语句 select o.xtype,o.name,cm.text from syscomments cm inner join sysobjects o on o.id=cm.i ...
- Centos|RHEL7以前解决网卡eth0相关问题
网络-网络-有网才有络络,哈哈!学习在于不断记录,问题记录多了就成大牛了.当大牛达到一定层次,都会回馈社会.研发推出新的东东! CentOS找不到ifcfg-eth0解决方法 问题描述: ifconf ...
- 【JavaEE企业应用实战学习记录】struts2实现登录并获取各个范围的数据
package sanglp; import com.opensymphony.xwork2.*; /** * Created by Administrator on 2016/10/6. */ pu ...
- 为Mac Terminal设置代理
参考链接:http://tz101.github.io/new-mac-os-x-yosemite-10-10-Xcode-Brew-Shadowsocks-Proxychains/ https:// ...
- 15-grep 简明笔
在文件中搜索模式 grep [options] pattern [file-list] 参数 pattern为正则表达式,file-list为grep要搜索的普通文本文件的路径名列表 选项 -c ...
- 60-chmod 修改文件的权限
修改文件的权限 chmod [options] who operator permission file-list (符号模式) chmod [options] mode file-list (绝对模 ...