【写在最前】SQLSTATE[HY000]这种形式的报错 不属于MySQL报错,是PDO报错(SQL状态错误)

【问题01】:SQLSTATE[HY000]: General error: 1023 program err:java.lang.NumberFormatException: For input string: \"2886861933\" (SQL: select * from `t_pandora_account_token` where `account_id` = '269708248855481922' and `status` = '1' and `app` = 'bim' and `via` = 'weApp')

原因分析:错误关键字 java.lang.NumberFormatException 这句话明确告诉了我们是数字格式异常,接着后面有 For input string:  \"2886861933\" 提示,这就告诉我们当前想把 \"2886861933\"转换成数字类型时出错了,这样就很确切了。

明明数据库中就是int类型,但此时提示string\"2886861933\"转换成数字类型时出错,就是因为   使用PDO查询mysql数据库时,执行prepare,execute后,返回的字段数据全都变为字符型。对于PHP这种弱类型的语言,影响不大。在做API返回数据时,如果类型与数据库不一致,对于Java和Objective C这些强类型,影响就很大了(mycat就是Java开发的)。

 

【问题02】:SQLSTATE[HY000] [2054] Server sent charset unknown to the client. Please, report to the developers (SQL: select * from `t_pandora_coupon_budget` where `status` = '1' and `type` = '10')

解决方法:$pdo->query("SET NAMES utf8");

由于mycat是Java开发的(ERROR 1115 (HY000): Unknown charset 'utf8'),所以$pdo->query("SET NAMES utf-8");

或配置文件设置:set charset utf-8

BUG01、SQLSTATE[HY000]: General error: 1023 program err:java.lang.NumberFormatException: For input string: \"2886862063\" (SQL: select * from `t_pandora_account_token` where `account_id` = '262034539203022996' and `status` = '1' and `app` = 'bim' and `via` = 'weApp'

问题说明:开发通过代码执行会抛出此错误,通过命令行连接mycat不会报错。而且SQL语句依然存在隐士转换和select * 的查询。

问题分析:

    1.查看表结构:

CREATE TABLE `t_pandora_account_token` (

  `access_token` char(32) NOT NULL DEFAULT '' COMMENT '令牌',

  `account_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '账户id',

  `shop_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '店铺id',

  `client_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '客户端版本',

  `token_ip` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '来源ip',

  `status` int(1) NOT NULL DEFAULT '1',

  `via` varchar(16) NOT NULL DEFAULT '' COMMENT '手机平台(iphone,android)',

  `cver` varchar(8) NOT NULL DEFAULT '' COMMENT 'APP?汾??',

  `token_expire` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '令牌过期时间',

  `last_refresh_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '最后互动刷新时间',

  `token_mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '令牌修改时间',

  `token_ctime` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '令牌创建时间',

  `app` varchar(20) NOT NULL DEFAULT '',

  PRIMARY KEY (`access_token`),

  UNIQUE KEY `idx_token` (`account_id`,`app`,`via`),

  KEY `shop_id` (`shop_id`) USING BTREE

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='账户令牌表';

 

细说表问题:1.主键为32位char类型的access_token值使得大大降低了性能

           2.token_expire和token_ctime为timestamp数据类型,默认值和保存的形式却为‘0000-00-00 00:00:00’

           3.表中字段注释出现了乱码

    2.查询相应的值信息

 

select * from t_pandora_account_token where account_id =262034539203022996 and status=1 and app='bim' and via='weApp \G;

*************************** 1. row ***************************

     access_token: 0000011838b2218093245e74032727ba

       account_id: 262034539203022996 

          shop_id: 0

        client_id: 7

         token_ip: 2886862063

           status: 1

              via: wx

             cver: 3.0

     token_expire: 2018-05-16 13:19:55

last_refresh_time: 0000-00-00 00:00:00

      token_mtime: 2018-05-17 13:19:55

      token_ctime: 2018-05-17 13:19:55

              app: bim

1 row in set (0.01 sec)

select inet_ntoa(2886862063);

+-----------------------+

| inet_ntoa(2886862063) |

+-----------------------+

| 172.18.4.239          |

+-----------------------+

亮点:把IP地址存成 UNSIGNED INT

    3.err:java.lang.NumberFormatException: For input string: "2886862063",数据类型转换异常

SQLSTATE问题分析及解决·第五话

把String类型转换为Integer类型,会抛出同样的异常

SQLSTATE问题分析及解决·第五话

或BigInteger b = new BigInteger(s);   //String 转换为 BigInteger

原因&解决办法01:Integer存储长度为32位。即-2^31~2^31-1; 即-2,147,483,648~2,147,483,647(2886862063>2147483647),此时将Integer换成BigInteger类型或long长整型。(MySQL中带符号的范围是-2147483648到2147483647。无符号的范围是0到4294967295。)

    因为暂时无法修改微信小程序或mycat源码,所以修改token_ip int(11) 为bigint(11),让其根据MySQL数据类型自动识别匹配BigInteger,问题解决。

ALTER TABLE t_pandora_account_token MODIFY COLUMN token_ip bigint(12) unsigned NOT NULL DEFAULT '0' COMMENT '来源ip';

解决办法02:开发代码对"2886862063"不做类型转换,直接利用函数转换为字符串IP(172.18.4.239),如果不涉及到该字段值的读取,强烈建议不要用select*,查询自己所需即可。(拿这次为例,其实最后用到的就access_token,但是开发为了方便还是用了select *)

 

BUG02、HUE查询跑错:Server error occurred: year=1000 is before 1900; the datetime strftime() methods require year >= 1900

报错原因:

File "/home/hue/hue/apps/rdbms/src/rdbms/api.py", line 48, in default

    return obj.strftime('%Y-%m-%d %H:%M:%S %Z')

ValueError: year=1000 is before 1900; the datetime strftime() methods require year >= 1900

问题分析:Python的strftime()是不支持转化1900前的日期,因为数据库中默认日期为1000-01-01 00:00:00

解决办法:通过str对象的format()方法根据需求格式化出想要的形式,而format()方法原生支持datetime对象的格式化。

修改前:

class ResultEncoder(json.JSONEncoder):

def default(self, obj):

if isinstance(obj, datetime.datetime):

return obj.strftime('%Y-%m-%d %H:%M:%S %Z')

elif isinstance(obj, datetime.date):

return obj.strftime('%Y-%m-%d %Z')

elif isinstance(obj, decimal.Decimal):

return float(obj)

return super(ResultEncoder, self).default(obj)

修改后:

class ResultEncoder(json.JSONEncoder):

def default(self, obj):

if isinstance(obj, datetime.datetime):

#return obj.strftime('%Y-%m-%d %H:%M:%S %Z')

return '{0.year:4d}-{0.month:02d}-{0.day:02d} {0.hour:2d}:{0.minute:2d}:{0.second:2d}'.format(obj)

elif isinstance(obj, datetime.date):

#return obj.strftime('%Y-%m-%d %Z')

return '{0.year:4d}-{0.month:02d}-{0.day:02d}'.format(obj)

elif isinstance(obj, decimal.Decimal):

return float(obj)

return super(ResultEncoder, self).default(obj)

 

特别注意:# su - hue

启动守护进程:$ /home/hue/hue/build/env/bin/supervisor &

 

 

 

 

 

 

 

 

相关文章:

  • 2022-01-23
  • 2022-12-23
  • 2023-01-17
  • 2022-01-05
  • 2021-05-26
  • 2022-12-23
  • 2021-06-18
  • 2021-08-17
猜你喜欢
  • 2021-10-05
  • 2022-02-14
  • 2021-12-01
  • 2021-12-04
  • 2022-01-08
  • 2021-06-21
  • 2021-09-28
相关资源
相似解决方案