mysql 实战问题处理

记录工作中使用mysql的疑难杂症及解决。

 

1 pipe broken or connection broken

        使用pol的mysql client端的连接莫名断开,一般都是由server端主动断开连接引发,需要查一下连接池中的maxIdle与mysql的wait_timeout,前者一定要小,否则connection会被server主动断开。

 

2 域名下的slave机的负载均衡

目前免费的连接池如c3p0、dbcp的线程池使用方式都是lifo,如果你恰好用域名来管理多个ip下的mysql slave实例,你可能会发现各个slave的连接、负载很不均衡。

解决:1)小心调整idleTime、min/max poolsize;2)增加一层proxy,来代理对这些线程池的connection管理。不过这样需要知道每个connection的ip,driver没有,有一个办法通过sql来获取:select @@hostname 查到server的host,这样配合lookup server,ip也拿到手了;另外也可以直接根据host来管理,不用ip,就是不太直观;3)自己写一个driver,不过需要时间和验证的过程~~~

 

3 对于唯一键删除+insert的复合操作(unbind + bind)

常见于:业务绑定时,如果已经bind了另外一个唯一键,需要先unbind,然后再bind。这是replace into的一展身手的地方。

有几点要注意:1)如果有多个唯一键(包括primary key),如果新插入的row中与多个唯一键相同,mysql会先删除多条,然后插入这一条;2)replace into不能获取之前那行的原始值,比如replace into xxx on duplicate key update set a=a+1 相当于: set a=default(a)+1;3)table中必须要有unique key,否则相当于insert;

mysql的处理算法:1)try insert;2)if false,del with uniqu/primary key;3)try insert again

 

4 计数器更新减到负数

问题:mysql存计数器时,字段一般为unsigned,这样如果减到负数,mysql会抛异常,而且容易导致slave卡。

解决:使用insert into xx values (?,?,greatest(count+?, 0))on duplicate key update count=greatest(count+?, 0),这样就规避了上述问题。注意values中也要用greatest,否则mysql会有warnings,导致异常抛出:"Out of range value for column 'count' at row 1 ".

 

5 字符集为utf8的table,部分字段无法插入

问题:部分特殊字符无法插入。

解决:对于mysql 5.5之前的版本,varchar改为varbinary;对于mysql5.5之后的版本,继续用varchar,但client的连接字符集改为utf8mb4。这样不仅可以解决特殊字符无法入库的问题,也不会额外使用更多存储空间,同时与之前的utf8兼容,升级不用担心,不过对于java的mysql驱动,需要5.1.13之后的版本才支持utf8mb4。

 

6 关于update的返回值问题

        问题:对于sql "update timeline set vflag=10 where id=1",如果id为1的row的vflag已经是10了,那执行sql. update()后返回值(影响的行数)是1,而非预期的0.

        原因:确实找到id=1的row,并进行了修改,如果需要返回值是0,需要修改sql:"update timeline set vflag=10 where id=1 and vflag<>10"

你可能感兴趣的:(mysql)