MySQL : The last packet successfully received from the server was XXX milliseconds ago

14年毕业写完论文没事干的时候,自己玩微信公众号开发,当时想做一个自然语言交互,其实就是想试一下lucene,但是当时建索引的时候偶尔会报这个错,一致不知道具体原因,去网上搜索但是天下文章一大抄,你抄我来我抄他,也没找到原因,后来因为工作中也没遇到过,感觉应该是自己当时水平不行就忘了这件事,前几天 fatsjson 和 druid 的作者温少突然在一个群里面说有人通过阿里工单反馈这个问题,他给追踪了一下,找到了原因,原来还是还是有人遇到这个问题,今天记录一下,希望对遇到这个问题的小伙伴有帮助,报错的信息大概就是: Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 20,820,001 milliseconds ago. The last packet sent successfully to the server was 20,820,002 milliseconds ago. is longer than the server configured value of ‘wait_timeout’. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property ‘autoReconnect=true’ to avoid this problem. at sun.reflect.GeneratedConstructorAccessor29.newInstance(Unknown Source) ………… 下面是温少分享的截图 ...

November 11, 2017 · 1 min · 88 words · Bridge Li

事务并发处理

前几天和同事讨论,老夫自以为对事务有了一定的了解,但当讨论的时候发现还是有些说不明白,所以周末的时间,又看了一遍带我入门北京尚学堂马士兵老师关于事务的讲解,这次做一下笔记,以供以后忘了的时候查询方便。这里默认读者对事务的ACID都有了了解,直接说事务并发时可能出现的问题和数据库的事务隔离级别 事务并发时可能出现的问题 说这个问题记得大学课堂上有一个很经典的例子就是:银行的存取款,这里也用这个例子说明(因为不知道wp博客怎么搞表格和怎么支持MD,所以就搞几张图片吧) ①. 第一类丢失更新(Lost Update) ②. dirty read脏读(读到了另一个事务在处理中还未提交的数据) ③. non-repeatable read 不可重复读 ④. second lost update problem 第二类丢失更新(不可重复读的特殊情况) ⑤. phantom read 幻读 看到这里可能会有读者对不可重复读和幻读有所迷惑,这两者有什么区别吗?不都是受另一个事务的影响,导致前后结果不一致吗?其实仔细看区别还是很明显的:幻读是关于数据库的delete和insert导致前后的数据不一致,而其他的情况都是数据的更新导致前后的数据不一致 数据库的事务隔离机制 其中在文档java.sql.Connection中有详细的说明,除了none(没有事务)之外,还有:1:read-uncommitted 2:read-committed 4:repeatable read 8:serializable(数字代表对应值)四种。 为什么取值要使用 1 2 4 8 而不是 1 2 3 4 1=0000 2=0010 4=0100 8=1000(位移计算效率高) 需要说明的是: 只要数据库支持事务,就不可能出现第一类丢失更新 read-uncommitted(允许读取未提交的数据) 会出现dirty read, phantom-read, non-repeatable read 问题 read-commited(读取已提交的数据 项目中一般都使用这个)不会出现dirty read,因为只有另一个事务提交才会读出来结果,但仍然会出现 non-repeatable read 和 phantom-read;使用read-commited机制可用悲观锁 乐观锁来解决non-repeatable read 和 phantom-read问题 repeatable read(事务执行中其他事务无法执行修改或插入操作 较安全)但仍然会出现phantom-read serializable解决一切问题(顺序执行事务 不并发,实际中很少用) ...

April 9, 2017 · 1 min · 74 words · Bridge Li

Spring aop应用之实现数据库读写分离

去年五月份的时候曾经写过一篇:Spring加Mybatis实现MySQL数据库主从读写分离,实现的原理是配置了多套数据源,相应的sqlsessionfactory,transactionmanager和事务代理各配置了一套,如果从库或数据库有多个的时候,需要配置的信息会越来越多,远远不够优雅,在我们编程界有一个规范:约定优于配置。所以就用Sping的aop实现了一个简单的数据库分离方案,具体实现代码放在了Github上,地址如下: https://github.com/bridgeli/practical-util/tree/master/src/main/java/cn/bridgeli/datasource 读者如果想使用再简单的方法就是把这个代码download下来,放到自己的项目里面,当然更优雅的方式是:打成jar包,放到项目里面了,具体打jar的方法,老夫就不在这里多说了,相信看这篇文章的读者肯定都会了。当然仅仅有这份代码,他们是不会自动生效的,既然是使用Spring的Aop实现数据库读写分离,所以肯定会有牵涉到Aop的配置了,所以在spring-mybatis.xml中有如下配置: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> <!&#8211; 配置写数据源 &#8211;> <bean id="masterDataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <property name="driverClassName" value="${bridgeli.jdbc.driver}" /> <property name="url" value="${bridgeli.jdbc.url}" /> <property name="username" value="${bridgeli.jdbc.username}" /> <property name="password" value="${bridgeli.jdbc.password}" /> <property name="validationQuery" value="${bridgeli.jdbc.validationQuery}" /> <property name="initialSize" value="1" /> <property name="maxActive" value="20" /> <property name="minIdle" value="0" /> <property name="maxWait" value="60000" /> <property name="testOnBorrow" value="false" /> <property name="testOnReturn" value="false" /> <property name="testWhileIdle" value="true" /> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <property name="minEvictableIdleTimeMillis" value="25200000" /> <property name="removeAbandoned" value="true" /> <property name="removeAbandonedTimeout" value="1800" /> <property name="logAbandoned" value="true" /> <property name="filters" value="stat" /> </bean> <!&#8211; 配置读数据源 &#8211;> <bean id="parentSlaveDataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <property name="driverClassName" value="${bridgeli.jdbc.driver}" /> <property name="validationQuery" value="${bridgeli.jdbc.validationQuery}" /> <property name="initialSize" value="1" /> <property name="maxActive" value="20" /> <property name="minIdle" value="0" /> <property name="maxWait" value="60000" /> <property name="testOnBorrow" value="false" /> <property name="testOnReturn" value="false" /> <property name="testWhileIdle" value="true" /> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <property name="minEvictableIdleTimeMillis" value="25200000" /> <property name="removeAbandoned" value="true" /> <property name="removeAbandonedTimeout" value="1800" /> <property name="logAbandoned" value="true" /> <property name="filters" value="stat" /> </bean> <bean id="slaveDataSource1" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close" parent="parentSlaveDataSource"> <property name="url" value="${bridgeli_slave1.jdbc.url}" /> <property name="username" value="${bridgeli_slave1.jdbc.username}" /> <property name="password" value="${bridgeli_slave1.jdbc.password}" /> </bean> <bean id="dataSource" class="cn.bridgeli.datasource.MasterSlaveDataSource"> <property name="targetDataSources"> <map> <entry key-ref="masterDataSource" value-ref="masterDataSource"/> <entry key-ref="slaveDataSource1" value-ref="slaveDataSource1"/> </map> </property> <property name="defaultTargetDataSource" ref="masterDataSource"/> <property name="masterSlaveSelector" ref="dataSelector"/> </bean> <bean id="dataSelector" class="cn.bridgeli.datasource.MasterSlaveSelectorByPoll"> <property name="masters"> <list> <ref bean="masterDataSource"/> </list> </property> <property name="slaves"> <list> <ref bean="slaveDataSource1"/> </list> </property> <property name="defaultDataSource" ref="masterDataSource"/> </bean> <aop:aspectj-autoproxy/> <!&#8211; mybaits 数据工厂 &#8211;> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> </bean> <!&#8211; 自动扫描所有注解的路径 &#8211;> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="cn.bridgeli.mapper" /> <!&#8211; <property name="sqlSessionFactory" ref="sqlSessionFactory" /> &#8211;> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property> </bean> <!&#8211; 数据库切面 &#8211;> <bean id="masterSlaveAspect" class="cn.bridgeli.datasource.MasterSlaveAspect"> <property name="prefixMasters"> <list> <value>save</value> <value>update</value> <value>delete</value> </list> </property> </bean> <aop:config> <aop:aspect id="c" ref="masterSlaveAspect"> <aop:pointcut id="tx" expression="execution(\* cn.bridgeli.service..\*.*(..))"/> <aop:before pointcut-ref="tx" method="before"/> </aop:aspect> </aop:config> <context:annotation-config /> <context:component-scan base-package="cn.bridgeli" /> </beans> 这样我们就很优雅的利用Spring的Aop实现了对数据库的读写分离,读的时候走slaveDataSource1这个数据源,写的时候走masterDataSource这个数据源。哎,等等,这里哪里体现了约定优于配置这一规范,他们怎么知道哪些方法走读库哪些走写库?同学你别急,仔细读读这个配置文件,你就会发现在第98行,配置了一个MasterSlaveAspect,也就是说代码里面service层(为什么是service层?)的方法以这里面配置的这些关键字打头,都将会走写库,所以当我们想让一个方法走主库的时候,必须在这个地方添加该方法的前缀或者用这里面已有的前缀,这就要求我们必须约定好走主库的方法的打头,即约定优于配置。

December 31, 2016 · 2 min · 297 words · Bridge Li