精华内容
下载资源
问答
  • 11-10号 (a连续相同数字2次的出现1次 ,a连续相同数字3次的出现0次,b连续相同数字2次的出现2次,b连续相同数字3次的出现2次,c连续相同数字2次的出现1次,连续相同数字3次的出现0次) 11-11号 (a连续相同数字2...
  • 现象 今天在做一个项目时, 将 tomcat maxThreads 加大, 加...在做压测时, 同时开了 1000 个线程, 并发发起 http 请求去访问 tomcat 服务, 结果在第一次访问 tomcat 时出现了一系列 redis 查询超时, 例如 10...

    现象

    今天在做一个项目时, 将 tomcat 的 maxThreads 加大, 加到了 1024, tomcat 提供的服务主要是做一些运算, 然后插入 redis, 查询 redis, 最后将任务返回给客户端

    在做压测时, 同时开了 1000 个线程, 并发发起 http 请求去访问 tomcat 的服务, 结果在第一次访问 tomcat 时出现了一系列的 redis 查询超时, 例如 1000 个并发发起 10W 次请求, 可能头 1W 次请求会有 2000 次左右的 redis 超时造成服务失败, 但是之后就再不会出现 redis 超时的情况.

    解决

    通过观察 vmstat, 发现在出现超时时, r (运行队列) 特别高, 达到 12~25, 持续时间为 2~3 秒, 这段时间出现了很多 redis 超时. 而以后不出现超时时, r 值都保持在 5 左右. 此时, 通过缩减 tomcat 线程数, 减到 200, 再重新测试, 则没有出现超时.

     

    分析

    这是因为我的 redis 客户端是异步客户端, 但是我在使用它的时候是用异步客户端模拟同步客户端执行(调用 future.get()), 客户端内部使用 netty 实现, netty 的工作线程只有 4 或 8 个. 当我们刚启动 tomcat 服务时, 没有预热, 系统性能较差, 此时排队任务多的话, 会让巨大的 tomcat 业务线程(1024个)占据 cpu 的任务队列, 而 netty 工作线程较少, 得不到 cpu 时间执行, 最后造成超时.

    这里最大的问题在于在同步的 tomcat 业务代码中使用了异步的 redis 客户端, 因为 tomcat 业务线程数量大, 占据了大量 cpu 时间, 让 redis 客户端线程得不到执行, 最后导致了问题出现.

    如果说这里将 tomcat 的业务处理改为异步处理 (使用 servlet 3.0), 那么则可以大量缩减 tomcat 的业务线程, 这样既可以减少业务线程切换, 又可以让 redis 客户端线程得到更多的执行时间.

     

    延伸 

    抛开使用异步的 redis 客户端不说, 如果使用的是一个传统的同步 db 客户端, 那么 db 客户端的执行线程就是业务线程, 线程的 cpu 时间是均等的, 则不会出现这个超时的问题. 那么应该如何界定何时应该启用多少线程? 

    当我们的业务线程内有 io 操作, 例如 mysql 的操作时, 如果这个操作很耗时, 例如需要执行 2s, 我们则应该分配更多地线程. 假设此时并发 1000 请求, 而只有 8 个业务线程, 那么这 8 个业务线程只能执行 8 个任务, 而且因为实在等待 mysql 的 io 返回, cpu 此时处于闲置状态, 另外的 992 个请求因为没有线程执行, 只能排队等待. 所以此时如果分配更多的业务线程, 则可以更有效地利用 cpu 资源.

    而如果业务处理是 cpu 密集型的, 则应该使用更少的线程. 因为此时 cpu 会处于繁忙状态, 增加更多地线程也不会让线程得到执行时间片, 反而会增加线程切换的开销.

     

    总结

    对于我的业务场景, 最好的方式应该是减少业务线程, 并将业务处理使用 servlet 3.0 改为全异步的方式. 原因是因为使用的是异步的 redis 客户端, 它不会让线程处于闲置的等待状态, 这样既能减少线程切换, 又能合理的分配 tomcat 业务线程与 redis 客户端线程的执行时间片.

    展开全文
  • 什么是幻读个事务查询2,得到记录条不同。MVCC 多版本并发控制undo logundo log有两个作用:提供回滚和多个行版本控制(MVCC)。undo log主要存储也是逻辑日志,比如我们要insert条数据,那undo log会...

    6325162dd4cc11da288a64789a4cf1a2.png

    什么是幻读

    一个事务查询2次,得到的记录条数不同。

    MVCC 多版本并发控制

    undo log

    undo log有两个作用:提供回滚和多个行版本控制(MVCC)。

    undo log主要存储的也是逻辑日志,比如我们要insert一条数据了,那undo log会记录的一条对应的delete日志。我们要update一条记录时,它会记录一条对应相反的update记录。

    insert undo log – 记录insert

    update undo log – 记录update和delete,undo 是逻辑记录,记录了每一行修改的值(前后项)。

    实现原理

    而MVVC则引入了另外一种并发控制,它让读写操作互不阻塞,每一个写操作都会创建一个新版本的数据,读操作会从有限多个版本的数据中挑选一个最合适的结果直接返回,由此解决了事务的竞争条件。

    多版本控制的核心是数据快照,而 InnoDB 则是通过 undo log 来存储数据快照。InnoDB 通过 undo log 保存了已更改行的旧版本的信息的快照。

    InnoDB 的内部实现中为每一行数据增加了三个隐藏列用于实现 MVCC 。

    DB_ROW_ID: 行标识(隐藏单调自增id)

    DB_TRX_ID: 插入或更新行的最后一个事务的事务标识符。(删除视为更新,将其标记为已删除)

    DB_ROLL_PTR:写入回滚段的撤消日志记录(若行已更新,则撤消日志记录包含在更新行之前重建行内容所需的信息)

    根据事物标识符及撤销记录决定读取的快照版本。

    如何解决幻读

    Mysql的默认隔离级别是Repeatable read(可重复读),这种隔离级别下会产生幻读问题,Mysql通过锁机制及多版本控制解决了幻读现象的发生,主要手段如下:

    快照读

    事务每次取数据的时候都会取创建版本小于当前事务版本的数据,以及过期版本大于当前版本的快照数据。普通的 select 就是快照读。

    当执行select操作是innodb默认会执行快照读,会记录下这次select后的结果,之后select 的时候就会返回这次快照的数据,即使其他事务提交了不会影响当前select的数据,这就实现了可重复读了。

    当前读

    在 InnoDB 中,默认为 Repeatable 级别,InnoDB 中使用一种被称为 next-key locking 的策略来避免幻读(phantom)现象的产生。

    主要采用next-key锁,即行锁和gap锁来控制。

    如select * from user where id =1 for update;

    如果有id为1的记录则会被加排它(X)锁,如果不存在,则会加上next-key锁,此时插入记录是会排出异常的,以此解决幻读问题。

    展开全文
  • 上游系统比较复杂,有mysql,db2,oracle等各种系统,之前数的系统比较简单,没有涉及到mysql数据库,涉及到的数据库表数据量也不是很大,因此之前也没有出现过问题;但是随着从上游系统抽数的表越来越多,涉及...
    我工作的大数据平台从上游系统抽数,由于上有系统比较复杂,因此采用自写的java代码从上游系统进行抽数,以应对不同的情况;
    上游系统比较复杂,有mysql,db2,oracle等各种系统,之前的抽数的系统比较简单,没有涉及到mysql数据库,涉及到的数据库表数据量也不是很大,因此之前也没有出现过问题;但是随着从上游系统抽数的表越来越多,涉及到了mysql的数据库表,这些表在开发环境上抽数没有关系,但是到生产上抽数时间特别长,且最后以报错的形式抽数失败,主要的报错信息有:
    java.lang.outofmemoryerror:java heap space;
    显示是堆溢出的情况;
    采用top指令在linux上查看情况,显示内存占用特别多,且cpu占用很大;经过分析,发现是mysql的 问题,这里参考了网上的一些博客,之前的代码都是采用如下方式:
    ps = (PreparedStatement) con.prepareStatement("select * from xxx",
    				ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
    		ps.setFetchSize(1000);
    

    它表示从上游系统表中查询数据,但是不是一次性拿出来,而是采用每次拿1000条的形式,拿出之后再从上游系统再拿数据,但是mysql不支持这种操作方式,而是一次性将所有的数据从mysql数据库中拿出来放到内存中,这样就可以理解了我这里出现的问题:
    由于上游系统游500多万条数据,一次性从上游系统拿到本地的linux服务器上,导致占用内存过大,这时需要进行gc,内存中的数据一直很多,一直进行gc,导致cpu占用的资源达到300%多。
    对于这个问题,可以采用如下的方式进行解决:
    ps = (PreparedStatement) con.prepareStatement(“select * from xxx”,
    ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
    ps.setFetchSize(Integer.MIN_VALUE);
    ps.setFetchDirection(ResultSet.FETCH_REVERSE);
    这样,mysql数据库表中的数据可以采用分段的方式进行数据获取,每次只获取指定的数据,然后再从数据库中拿取数据;

    展开全文
  • 数据库资料

    2018-04-01 22:00:33
    SQL编程,实现功能强大的查询掌握创建索引、视图,快速访问数据库 掌握创建存储过程,实现复杂业务规则理解触发器原理,实现高级约束目标了解设计数据库的步骤掌握如何绘制数据库的E-R图理解数据库的规范化-...
  • 网上搜是链接池满才导致这个问题出现,然后我查链接池最大链接只有150个,然后我下午改为500个后就好。刚才链接软件又报出这个错误,我看连接池发现又满。我自己就没怎么连然后用这个sql语句查询下看...
  • 问题现象 在某个工作日,突然收到线上服务告警,有大量...当第一次告警产生时,第一反应是可能上层服务有大量接口调用,并且涉及到一些复杂SQL查询导致数据库连接不够用,但是在分析接口调用情况后发现异常

    问题现象

    在某个工作日,突然收到线上的服务告警,有大量的请求延时产生,查看线上服务发现基本上都是获取数据库连接超时,而且影响时间只有3~4秒钟,服务又恢复了正常。隔了几分钟之后,又出现了大量的告警,还是影响3~4秒后又恢复正常。 由于我们是底层服务,被重多的上层服务所依赖,这么频繁的异常波动已经严重影响到了业务使用。开始排查问题

    排查过程

    DB的影响?

    1. 当第一次告警产生时,第一反应是可能上层服务有大量的接口调用,并且涉及到一些复杂的SQL查询导致数据库连接数不够用,但是在分析了接口调用情况后发现异常前后的请求并没有明显的变化,排除突发流量造成的影响
    2. 查询DB情况,负载良好,无慢查询,排除DB造成的影响

    容器或JVM的影响?

    排除了DB的影响之后,再往上排查容器的影响 我们再次回过头看异常告警,发现在每一波告警的时间段内,基本上都是同一个容器IP所产生,这个时候基本上已经有80%的概率是GC的问题了。 查询告警时间段内的容器CPU负载正常。再看JVM的内存和GC情况,发现整个内存使用曲线是像下面这样:

    Heap

    数据库连接池引起的FullGC问题,看我如何一步步排查、分析、解决

     

    Old Gen

    数据库连接池引起的FullGC问题,看我如何一步步排查、分析、解决

     

    从上图可以发现内存中存在长时间被引用,无法被YongGC所回收的对象,并且对象大小一直在增长。直到Old Gen被堆满之后触发Full GC后对象才会回收。

    临时措施

    现在问题已经找到了,到目前为止只是3台实例触发了FullGC,但是在查看其它实例内存使用情况时,发现基本上所有的实例Old Gen都快到达临界点了。所以临时解决方案是保留一台实例现场,滚动重启其它所有的实例,避免大量的实例同时进行FullGC。否则很可能导致服务雪崩。

    原本服务是有设置jvm监控告警的,理论上来说当内存使用率达到一定值时会有告警通知,但是由于一次服务迁移导致告警配置失效,没有提前发现问题。

    问题分析

    什么对象没有被回收?

    目前了解到的情况: 内存无法被YoungGC回收,且无限增加,只有FullGC才能够回收这批对象

    jmap -histo:live pid

    数据库连接池引起的FullGC问题,看我如何一步步排查、分析、解决

     

    先简单在线上观察了一波,排第2的HashMap$Node看起来比较异常,但是看不出更详细的情况了。最好的办法还是将内存快照dump出来,使用MAT分析一波

    jmap -dump:format=b,file=filename pid 

    数据库连接池引起的FullGC问题,看我如何一步步排查、分析、解决

     

    使用MAT打开之后,可以发现很明显的问题:

    class com.mysql.cj.jdbc.AbandonedConnectionCleanupThread

    这个类占用了80%以上的内存,那么这个类是干嘛的呢? 看类名就知道,应该是MySQL Driver中用来清理过期连接的一个线程。让我们看一下源码:

    数据库连接池引起的FullGC问题,看我如何一步步排查、分析、解决

     

    这个类是一个单例,会且仅会开一个线程,用来清理那些没有被显式的关闭的数据库连接。

    可以看到这个类里面维护了一个Set

    private static final Set<ConnectionFinalizerPhantomReference> connectionFinalizerPhantomRefs = ConcurrentHashMap.newKeySet();

    对应我们上面看到的内存占用率排第二的HashMap$Node,基本上可以确定大概率是这里存在内存泄露了。在MAT上使用list_object确认一发:

    数据库连接池引起的FullGC问题,看我如何一步步排查、分析、解决

     

    果然没错,罪魁祸首找到了! 那么它里面存的是啥东西呢? 为什么一直增长且无法被YoungGC回收?看名字ConnectionFinalizerPhantomReference 我们可以猜到它里面保存的应该是数据库连接的phantom引用

    什么是phantom reference? 当一个对象只有phantom reference引用时,则会在虚拟机GC时被回收,同时会将phantom reference的对象放入一个referenceQueue中。

    让我们来跟踪源码确认一下

    数据库连接池引起的FullGC问题,看我如何一步步排查、分析、解决

     

    数据库连接池引起的FullGC问题,看我如何一步步排查、分析、解决

     

    果然是PhantomReference,里面存放的是创建的MySQL连接,看一下是在哪里被放进来的:

    数据库连接池引起的FullGC问题,看我如何一步步排查、分析、解决

     

    数据库连接池引起的FullGC问题,看我如何一步步排查、分析、解决

     

    可以看到,每次创建一个新的数据库连接时,都会将创建的连接包装成PhantomReference后放入connectionFinalizerPhantomRefs中,然后这个清理线程会在一个无限循环中,获取referenceQueue中的连接并关闭。

    只有在 connection对象 没有其它的引用,仅存在phantom reference时,才能够被GC,并且放入referenceQueue中

    为什么Connection会无限增长?

    现在问题找到了,数据库连接被创建之后,则会放入connectionFinalizerPhantomRefs中,但是由于某种原因,连接前期正常使用,经过了多次minor GC都没有被回收,晋升到了老年代。但是一段时间过后,由于某种原因连接失效,导致连接池又新建了连接。

    我们项目用的数据库连接池是Druid,以下为连接池配置:

    数据库连接池引起的FullGC问题,看我如何一步步排查、分析、解决

     

    可以看到是设置了keepAlive,且minEvictableIdleTimeMillis设置的是5分钟,连接初始化之后,在DB请求数没有频繁的波动时,连接池应该都是维护着最小的30个连接,且会在连接空闲时间超过5分钟时进行一次keepAlive操作:

    数据库连接池引起的FullGC问题,看我如何一步步排查、分析、解决

     

    数据库连接池引起的FullGC问题,看我如何一步步排查、分析、解决

     

    理论上来说,连接池是不会频繁的创建连接的,除非有活跃连接很少,且存在波动,并且keepAlive操作没有生效,在连接池进行keepAlive操作时,MySQL连接就已经失效,那么则会丢弃这个无效连接,下次再重建。

    下面就是验证这个猜想,我们首先查看我们的活跃连接数,发现在大部分时候,单实例的数据库的活跃连接数都在3~20个左右波动,并且业务上还存在定时任务,每隔30分钟~1个小时会有大量的DB请求。 Druid既然有每隔5分钟有心跳行为,那为什么连接还会失效? 最大的可能是MySQL服务端的操作,MySQL默认服务端的wait_timeout是8小时,难道是有变更对应的配置?

    show global variables like '%timeout%'

    数据库连接池引起的FullGC问题,看我如何一步步排查、分析、解决

     

    果然,数据库的超时时间被设置成了5分钟!那么问题就很明显了。

    结论

    1. 空闲连接依赖于Druid的keepAlive定时任务来进行心跳检测和keepAlive,定时任务默认每60秒检测一次,并且只有当连接的空闲时间大于minEvictableIdleTimeMillis时才会进行心跳检测。
    2. 由于minEvictableIdleTimeMillis被设置为了5分钟,理论上空闲连接会在5分钟±60秒的时间区间内进行心跳检测。但是由于MySQL服务端的超时时间只有5分钟,所以大概率当Druid进行keepAlive操作时连接已经失效了。
    3. 由于数据库的活跃连接是波动的,且min-idle设置的是30,活跃连接处于波峰时,需要创建大量的连接,并且维护在连接池中。但是当活跃降到低谷时,大量的连接由于keepAlive失败,从连接池中被移除。周而复始。
    4. 每次创建连接时,又会将Connection对象放入入connectionFinalizerPhantomRefs中,并且由于创建完之后连接是处于活跃状态,短时间内不会被miniorGC所回收,直至晋升到老年代。导致这个SET越来越大。

    解决

    知道问题的产生原因,要解决就很简单了,将minEvictableIdleTimeMillis设置为3分钟,保证keepAlive的有效性,避免一直重建连接即可。

    展开全文
  • 注意:alter modify不支持一次修改多个列,但是Oracle支持多列修改 但是MySQL可以通过多个modify方式完成: alter table user modify tel varchar(15) default '02087654321' first, modify name varchar(20) ...
  • 问题现象 在某个工作日,突然收到线上服务告警,有大量...当第一次告警产生时,第一反应是可能上层服务有大量接口调用,并且涉及到一些复杂SQL查询导致数据库连接不够用,但是在分析接口调用情况后发现异常
  • 他是几本书的作者,这包括Professional SQL Server 2005 XML(Wrox,2006)和Professional LINQ(Wrox,2008),他还为SQL PASS Community Connector写每两周一次的特辑文章。他也为好几个网站供稿,这包括Wrox...
  • 他是几本书的作者,这包括Professional SQL Server 2005 XML(Wrox,2006)和Professional LINQ(Wrox,2008),他还为SQL PASS Community Connector写每两周一次的特辑文章。他也为好几个网站供稿,这包括Wrox...
  • 话说某日,小飞鱼将一套OA系统刚部署上,打开几个表单看了一下,其中个就出现了下面情况,本来应该显示输入框控件地方都变成了花括号和英文数字,这是哪里出了问题呢? 尝试查看相关流程工作,也是报错...
  •  本书由多位工作在数据库维护一线工程师合著而成,包含精心挑选的数据库诊断案例与性能优化实践经验,内容涉及oracle典型错误分析和诊断,各种sql优化方法(包括调整索引,处理表碎片,优化分页查询,改善...
  • 4、把S表所有行一次性地加到临时表ST中。 select * into ST from S; 5、在SC表中把所有学生成绩加2分。 update sc set score=case when score+2>100 then 100 else isnull(score,0)+2 end; 6、在ST表中...
  • 问题现象 在某个工作日,突然收到线上服务告警,有大量...当第一次告警产生时,第一反应是可能上层服务有大量接口调用,并且涉及到一些复杂SQL查询导致数据库连接不够用,但是在分析接口调用情况后发现异常
  • 但是部署到正式环境之后,总是会卡死(个上午重启3~4tomcat),虽然不能确定一定是这里造成,但是作为对照个没有部署新版本系统却相安无事,不能不让人往这个地方猜想。 有没有这方面经验大神给...
  • pg数据库sql优化总结

    千次阅读 2018-07-30 10:00:39
    pg数据库用近1年多,操作数据量也越来越大,生产上也多次出现查询现象,系统在高峰时间cpu使用率冲高达到100%,经分析罪魁祸首就是慢查询了。  第、排查,分析索引  因业务量增大,很多单表记录已经...
  • 今天又出现了更严重问题 昨天解决完问题 今天早些时候 出现了系统无法登录 查询日志定位应该数数据库的问题 后面发现是磁盘满了 其实还是昨天出现问题导致, 死循环刷了特别多日志,,导致磁盘空间不足 导致...
  • 当想要进行增量备份时(包含上一次完全备份或增量备份之后所有更改),应使用FLUSH LOGS回滚二进制日志。然后,你需要将从最后完全或增量备份某个时刻到最后某个点所有二进制日志复制到备份位置。这些二进制...
  •  还是在2008年7月时候,一次在线闲聊中,我和阿里巴巴B2B童家旺谈及写本数据库方面技术图书想法。我曾与他在一个DBA团队共事,深知他技术功力。不过相对于图书创作来说,他更倾向于翻译一本质量过硬...
  • SQL-数据库刷题

    2019-10-04 20:39:26
    因是个人总结,只列出对自己有用的或较难的: 下面这道题,第一次拿到,我尝试用 开窗函数 ROW_NUMBER()OVER() 编号,但是发现不能够...编写一个 SQL 查询,查找所有至少连续出现次的数字。 +----+-----+ | Id | ...
  • 通过作者历时3年写作,本书介绍Oracle安装及卸载、数据库的启动关闭、表空间和数据文件管理、Oracle网络管理、口令文件管理、内存管理、进程管理、用户管理、数据导入导出、备份与恢复、模式对象管理...
  • 通过作者历时3年写作,本书介绍Oracle安装及卸载、数据库的启动关闭、表空间和数据文件管理、Oracle网络管理、口令文件管理、内存管理、进程管理、用户管理、数据导入导出、备份与恢复、模式对象管理...
  • 继昨天服务器上应用 CPU占用过高 后面该应用宕掉了以后今天又出现了更严重问题 昨天解决完问题 今天早些时候 出现了系统无法登录 查询日志定位应该数数据库的问题后面发现是磁盘满了 其实还是昨天出现问题导致...
  • 适用于在一次性插入100-1000+条记录时, 提高效率。默认值是8M。可以针对数据量大小,翻倍增加。 myisam_sort_buffer_size = 1024M # MyISAM设置恢复表之时使用缓冲区尺寸,当在REPAIR TABLE或用CREATE INDEX...

空空如也

空空如也

1 2 3 4 5 ... 19
收藏数 369
精华内容 147
关键字:

数据库查询出现了一次的数