mysql中错误码1406 data too long在jdbc和命令行的不同表现及处理

2016/07/04 21:56:03 No Comments

今天在同事开发过程中碰到一个mysql的错误码:1406,显示的错误信息为 data too long for column,而导致相应的事务被回滚.将此错误码(google 关键字 mysql 1406),即搜索到相应的错误信息,即相应的插入数据比实际的列的大小更大.然后,报相应的错误信息,最终处理失败.

但是,对于这条sql语句,如果将语句贴到命令行去执行,即得到另外一个结果.sql不会报错,但再次查询相应的数据信息,会发现插入的数据被自动截断了.在这种情况下,实际上插入的数据是错误的,即因为不同的行为得到不同的结果.

然后,再次google(关键字 mysql自动截断)会发现这两种情况是因为使用了不同的sql_mode导致.获取相应的sql_mode命令可以如下所示(笔者mysql为mariadb 10.1)

select @@sql_mode;

获取的数据信息为:NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION.

这种情况下,即会产生自动截断的设置.可以通过set @@sql_mode="xxx"来修改.影响截断地设置为 strict_trans_tables 或者 strict_all_tables.将其设置为其中之一即可.

反之,使用默认的jdbc连接mysql时,同样通过命令获取相应的数据,结果为
NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
会发现相应的设置并不与命令行相同.

这里的原因在于,在mysql的jdbc驱动中,之前也是与命令行相同,但为了保证与jdbc规范相符(具体的规范没找到),引入了配置变量 jdbcCompliantTruncation.此变量可以在连接字符串中,追加并设置为false.其默认值为true.
在具体的mysql jdbc实现中(当前版本为5.1.39),此变量会在类ConnectionImpl中判定.如果为true,并且版本大于5.0.2,则会发语句set sql_mode=xxx 来进行重新设置.其重新设置的值,即在之前提到值的基础之上,追加值 STRICT_TRANS_TABLES. 然后,在此设置的影响下,插入数据超长即会直接报错,而不是自动截断.

(more…)

服务端推送websocket和sse场景及应用

2016/07/04 14:21:44 No Comments

在当前的系统中, 涉及到使用长连接进行通信的应用越来越多,许多应用场景也已经不再满足于通过常规的http来进行短时间的交互.而是希望像传递的cs结构一样,常时间地挂在服务器上,以接收一定的数据信息.可以理解为使用浏览器来作传统cs客户端的事情.

经过几天简单地了解,就当前使用java进行后端推送类的服务进行了一些了解,就应用场景,开发方式以及一些特定的实现进行了简单的demo处理.

应用场景

  1. 都可以进行服务端推送,并且都是使用长连接来进行.但两者的实现又有一点不同,sse仍使用http协议,并且使用相同的链接发送正常的http协议报文.而websocket是使用http协议进行握手,然后再使用同一个链接进行websocket协议的通信.
  2. websocket可以进行双向的通信,即服务端可以往客户端发信息,客户端也可以向服务端发信息.而sse是单向的,只能由服务端往客户端发.
  3. websocket自带连接的保持,即通过ping/pong协议保证连接可以始终维持,sse没有这个保证,不过可以参考ping/pong协议,自己周期性地发送信息来同样地进行处理.比如,5秒往客户端发一个特别的信息(通过type/name进行区分).其次,因为是基于浏览器的使用,sse有一个特性,就是浏览器发现一个连接断掉了,就会自动地进行重联,即重新发送请求.这样,服务端也不用担心连接被断开,不过需要处理新的请求必须和上一次请求的内容相连续,以及新的推送注册.
  4. 因为都是使用http协议进行起始处理,因此在签权上都可以使用到http协议本身的一些东西,比如header/cookie签权.在相应的握手阶段,通过读取cookie(session)来保证相应的请求必须是经过授权的,也可以用于定位使用人.甚至可以通过这些信息保证单个用户只能有一个请求,避免重复请求
  5. 由于都是基于浏览器使用,因此建议的数据传输都是文本型.虽然websocket支持二进制frame传输,不过一些都不建议使用.sse只能传输文本
  6. 不管是websocket还是sse,在用于通信时,都建议只用于进行数据的推送,而不是进行完整的应用处理.这里可以理解为,常规的业务处理仍然交给后端的服务来处理.这样,即可以使用之前的业务开发的优势,又可以使用推送的优势.而不是走向另一个级端,即所有的信息都想通过推送来传递.

(more…)