工作杂记

 

记录一些零碎

【MYSQL】

  • 连接方式。连接 mysql 服务器可以通过 tcp/ip,也可以通过 socket(仅限于本地) 。当在连接命令中指定 mysql 服务器 ip 时,连接方式为 tcp/ip 。当连接命令中不指定连接 ip 或 或者 ip 为 localhost 时,连接方式为 socket。如果使用 socket 连接时,mysql 默认从 /tmp 目录下寻找 mysql.sock 文件,如果没有找到,并且没有在全局选项文件里指定,那么会报“Can't connect to local MYSQL server through socket '/tmp/mysql.sock'” 的错误。这种情况下,可以尝试重启 mysql 服务器,重启后进入 /tmp 目录下查看是否生成 mysql.sock,如果没有,先使用命令查找下是否存在 mysql.sock 文件。比如:find / -name mysql.sock,或者 whereis mysql.sock。查询到位置后,那么可以通过修改 /etc/my.cnf 文件:
    [mysqld]
    # 示例位置
    socket=/opt/mysql/tmp/mysql.sock
    [client]
    socket=/opt/mysql/tmp/mysql.sock
     在文件中指定该位置,然后重启 mysql。注意,客户端和服务器需要同时指定同一个位置!
  • mysql 5.7 在创建联合主键时,每个主键均不能为空!即 NOT NULL。
  • 触发器 trigger。现假设有两张表 A 和 B。在 A 表进行 INSERT 操作后,对 B 表的 VERSION 字段做 + 1 的更新操作:
    -- -----------------
    -- 触发器
    -- -----------------
    DROP TRIGGER IF EXISTS `test_trigger`;
    DELIMITER ;;
    CREATE TRIGGER `test_trigger` AFTER INSERT ON `A` 
    FOR EACH ROW
    BEGIN
        UPDATE `B` SET VERSION = VERSION + 1 WHERE ID = NEW.B_ID;
    END
    ;;
    DELIMITER ;
     其中 DELIMITER 是 mysql 中的分隔符,默认的分隔符为分号“;”,当一次输入的语句不止一行,且行与行之间有分号,那么需要对该段语句重新定义分隔符。DELIMITER ;; 表示从这行开始分割符为 ;;,当语句结束后需要变回原来的单分号,那么指定 DELIMITER ; 即可。NEW.B_ID 中的 NEW 表示 A 表插入后的数据,这个是特定语法,对应的还有 OLD
  • 视图 VIEW
       什么是视图? 视图是一张 虚拟表,存放了某个预先写好的查询语句执行的结果,对于一些复杂查询来说,当我们需要再次执行复杂查询时,不需要在重新写冗长的查询语句,直接从这张虚拟表中查询即可。
-- AS 后面接需要查询的语句
CREATE VIEW `test_view` AS 
(SELECT A.xx, B.yy FROM `A` LEFT JOIN `B` ON A.b_id = B.id)
2. 修改视图
CREATE OR REPLACE VIEW `test_view` AS
(SELECT ...)
 在使用视图时,直接当成普通表来使用即可。
  • 创建分区 PARTITION 

        通过 show plugins; 指令可以查看当前 mysql 数据库所拥有的插件,如果存在名为 partition 的插件,说明该数据库支持创建表分区。另: show engines; 指令可以查看所有支持的存储引擎。

 

  • 索引 INDEX

1. 索引的分类

 

 

 

【问题定位】

  •  遇到一个“每天刷卡记录都会丢失一小部分”的问题,由于有主动从门禁设备中获取已保存的数据的接口,因此每天“丢失”的那部分,可以通过 web 页面操作补上,但终归是个问题。在第一次排查问题时,发现后台处理(批量处理)刷卡记录的速度明显跟不上记录上报的速度并且发现“补数据”的操作发生时,后台尚未处理完刷卡记录,于是认为数据并未丢失而是尚未处理完成,然后通过添加索引优化了后台处理的速度。但是,之后的一两天,发现这个问题依然是存在的。于是,再次分析日志,但是似乎并没有和刷卡记录入库相关的异常发生(存在一个与此问题无关的异常,且数量较多)。然后我想,这个业务是一条线程单独处理的,会不会是分配任务队列的 Size 不够,可是也不对,上报的刷卡记录数量总数与队列 Size 相差 半个到一个数量级,不可能满,而且就算队列满了也会抛出相应异常的。于是陷入僵局...最后在查询异常日志时,用一个在 catch 块中打印的字符串搜到了这个异常,巧合的是,这个异常的原因竟然与那个狂打的,无关的异常一摸一样,都是由 mybatis 产生的“期望得到一个结果,但是找到了多个”异常,这就是在一开始按异常查找没发现问题的原因,然后就转为了“为什么会得到两个结果”的问题......其实一开始如果提出问题时可以更具体到“每天都是缺少几十条数据”,亦或者是“谁的数据每天都会缺失”,那么会比较肯定是批量执行时异常(查异常时,差点就以为批量执行没发生异常)。而且每天批量的数据操作,一旦中间数据出错,会出现比较规律性的一组数据失败,这给我的印象是比较深刻的。

 

【Controller 的处理】

  • BaseController。在 controller 中,许多步骤是重复的,比如:分页对象封装,Session 的获取以及返回形式的封装(如:返回json,返回文件上传结果等);
  • 对象转换。接收客户端数据的通常为 VO(Value Object)对象,它是一个值对象,也可以说是业务对象,这个对象需要具备一个方法将 VO convert to(转换为) PO (Persistent Object)对象。PO 对象的字段通常对应的是数据表的字段,因此 VO 对象字段与 PO 对象字段可能不同(可以相同),这一点在完全 ORM 框架中特别明显,在 mybatis 中不太明显;在 service 接口数据返回后,需要将 PO 对象转换为 VO 对象,因为有时候数据库存储的并不是具体的中文,而是类似“0/1”,“YES/NO”,或者存的是个枚举的值,这些数据在返回 客户端之前需要转换为具体的内容,一些不需要的数据也可以直接丢弃。
  • 返回对象。对于返回给客户端的数据,除了具体后台处理后得到的(通常是个对象)外,最好有个请求结果的提示,如 success 或 error(failed);还可以定义错误码等。那么可以,将这些数据再封装为一个返回对象。这样代码的整体性会比较好。

【关于分页】

  • 接收参数。对于接收分页参数的 VO 对象,可以抽取出一个父类,带有 pageNum,pageSize 字段,如果考虑到可能有排序的需求,那么加上排序字段对象,和排序顺序字段,这样可以通过客户端传递排序参数就能完成不同的排序,而服务端代码无需变动(前提是在 sql 中预先判断排序字段非空则排序)。
  • Page对象。通常分页参数至少有三个:当前页,每页数量,查询条件,在每个接口中传递略有些麻烦,可以封装一个 Page 对象,除上述参数外作为字段外,还需加上结果总数字段。

【log4j】

格式参数表示及含义:

  • %d:日期,通过大括号定义格式,如:%d{yyyy-MM-dd hh:mm:ss.SSS}
  • %p:日志等级,包括 DEBUG,INFO,WARN,ERROR,FATAL,等级依次提高
  • %t:线程名称
  • %m:具体日志信息
  • %c:打印日志的类(在哪个类打印的)
  • %F:日志类的名称
  • %n:换行符
  • %L:日志发生的位置(类名,方法名,行号等)

猜你喜欢

转载自getthrough.iteye.com/blog/2418266