10月22
一、问题
### Cause: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction;


现象:接口响应时间超长,耗时几十秒才返回错误提示,后台日志中出现Lock wait timeout exceeded; try restarting transaction的错误

二、原因分析
使用InnoDB表类型的时候,锁等待超过了innodb_lock_wait_timeout(默认是50s)设置的时间,所以报错

三、可能出现场景
1、在同一事务内先后对同一条数据进行插入和更新操作

2、多台服务器操作同一数据库

3、瞬时出现高并发现象,spring事务造成数据库死锁,后续操作超时抛出异常

4、事务A对记录C进行更新/删除操作的请求未commit时,事务B也对记录C进行更新/删除操作。此时,B会等A提交事务,释放行锁。当等待时间超过innodb_lock_wait_timeout设置值时,会产生“LOCK WAIT”事务。

四、解决方案
1、【治标方法】innodb_lock_wait_timeout 锁定等待时间改大

SELECT
  @@innodb_lock_wait_timeout;

innodb_lock_wait_timeout = 50

修改为
SET @@innodb_lock_wait_timeout = 500;

innodb_lock_wait_timeout = 500

缺点:全局更改,影响也是全局的,等待时间加长,容易使等待事务增多导致堆积问题。

2、【治标方法】事务信息查询

SELECT * FROM information_schema.innodb_trx

查到一个一直没有提交的只读事务(trx_state=”LOCK WAIT”),找到对应线程,执行:

kill 线程ID(trx_mysql_thread_id)

3、【治标方法】如果杀掉线程依然不能解决,可以查找执行线程耗时比较久的任务,kill掉

SELECT * from information_schema.`PROCESSLIST` WHERE Time > 1000 AND USER = 'xxx' ORDER BY TIME desc;

kill 线程ID

4、【根本解决方法!】找到锁表的事务,分析锁表原因,进行优化。

实例:司机APP进行运单签收,需要对et_waybill_info表某些记录进行更新操作。一直处于锁等待状态,直到超时报错。

经排查,发现:系统定时器定时执行任务,将所有未标识亮的已装车或签收的运单,按批次处理,如果运单装车了但长时间未上传GPS、温湿度等信息,会一直被定时器处理。数据量越积越大,队列长时间等待,对et_waybill_info表锁住没有释放,致使签收要操作et_waybill_info表无法拿到锁,进行数据操作。

临时解决方案:停掉定时器任务

根本解决方案:优化定时器

五、预防措施
1、开始事务(@transtion)指定超时时 间

例:@Transactional( rollbackFor = Exception.class , isolation = Isolation.REPEATABLE_READ, timeout = 30)

2、事务中存在批量修改、删除语句的时候,where条件尽量加索引

3、事务中存在批量修改、删除语句的时候,尽可能减少事务的执行时间

4、减少并发线程数

六、相关信息
1、innodb_lock_wait_timeout和lock_wait_timeout
innodb_lock_wait_timeout:InnoDB事务等待一个行级锁的时间最长时间(单位是秒),超过这个时间就会放弃。默认值是50秒

lock_wait_timeout:获取元数据锁的超时时间。这个适合用于除了系统表之外的所有表(mysql库之外)。

区别于innodb_lock_wait_timeout是针对dml操作的行级锁的等待时间 ,而lock_wait_timeout是数据结构ddl操作的锁的等待时间

2、事务相关表
INNODB_TRX  当前运行的所有事务



INNODB_LOCKS  当前出现的锁,查看正在锁的事务



INNODB_LOCK_WAITS  锁等待的对应关系,查看等待锁的事务



3、information_schema和performance_schema
information_schema:对数据库元数据的抽象分析,由此提供了SQL语句方式来查询数据库运行时状态,每次对infomation_schema的查询都产生对metadata的互斥访问,影响其他数据库的访问性能。这张数据表保存了MySQL服务器所有数据库的信息。如数据库名,数据库的表,表栏的数据类型与访问权限等。

performance_schema:内存型数据库,使用performance_schema存储引擎,通过事件机制将mysql服务的运行时状态采集并存储在performance_schema数据库。用于监控MySQL server在一个较低级别的运行过程中的资源消耗、资源等待等情况。

七、总结
1、当看到mysql报错时,可以根据报错的信息及错误号去分析报错原因,然后冷静分析,透过现象看本质,从根本上解决问题。少用治标不治本的方案,还可能会带来其他问题。

2、了解了mysql里几张事务相关表

3、初识information_schema和performance_schema
10月20
remote: The project you were looking for could not be found.

在使用Git客户端克隆和pull远程仓库的时候报错:提示找不到上游仓库,但是地址是正确的!

问题原因解析:

因为自己的项目不止一个 又有自动保存git密码的功能,当clone第二个项目的时候和之前的git用户不是同一个就会报这个错误!

解决方案:

在自己的项目路径上加上自己的用户名,
例如:
Git clone http://10.1.100.1:0000/credit/code/heck.git (失败)
Git clone http://用户名@10.1.100.1:0000/credit/code/heck.git(成功)

或者clear掉之前拉的项目保存的用户名和密码认证的数据。
10月18
    最近在维护一个几年前的项目,发现供应商报价本来为decimal类型保留两位小数的数据,结果通过ifnull后变成四舍五入保小一位小数了,排查了很久才现是由于ifnull函数引起的问题。      
SELECT
        IFNULL( (select CREATION_DATE  from  pur_bidding_supplier_line pbsl where  pbsh.HEAD_ID = pbsl.HEAD_ID  order by CREATION_DATE desc LIMIT 1 ) ,  pbsh.CREATION_DATE) as CREATION_DATE,
        IFNULL((select LINE_ID  from  pur_bidding_supplier_line pbsl where  pbsh.HEAD_ID = pbsl.HEAD_ID  order by CREATION_DATE desc LIMIT 1 ) ,0) as LINE_ID,
        CONVERT(IFNULL((select QUOTED_PRICE  from  pur_bidding_supplier_line pbsl where  pbsh.HEAD_ID = pbsl.HEAD_ID  order by CREATION_DATE desc LIMIT 1 ),99999999999999999999999),decimal(20,2)) as QUOTED_PRICE,
            pbsh.SUPPLIER_ID,
            ps.SUPPLIER_NAME,
            pe.PRO_ID ,

            ( select glook from pur_program  p  where p.pro_id=pe.PRO_ID) as GLOOK,
            ( select AGENTLOOK from  pur_program   p where p.pro_id=pe.PRO_ID) as AGENTLOOK
        FROM

            pur_bidding_supplier_head pbsh,
            pur_evaluation pe,
            pur_supplier ps
        WHERE
           pe.EVALUATION_ID = pbsh.EVALUATION_ID
          AND ps.SUPPLIER_ID = pbsh.SUPPLIER_ID
          AND pe.PRO_ID = #{0}
        ORDER BY
            pbsh.CREATION_DATE DESC

最后通过上面红色部分的convert函数来实现转成保留两位小数。
转换前的数据
2021-07-06 10:43:00  26506  88889.0  6302  李盛超测试
2021-07-06 10:47:06  26518  1500.1  6306  黄彤测试账号
2021-07-06 10:43:00  26508  6666.1  6304  顾志坚测试账号

转换后的数据
2021-07-06 10:43:00  26506  88889.02  6302  李盛超测试
2021-07-06 10:47:06  26518  1500.08  6306  黄彤测试账号
2021-07-06 10:43:00  26508  6666.05  6304  顾志坚测试账号

10月8
mybatis 映射文件中,if标签判断字符串相等,两种方式:
因为mybatis映射文件,是使用的ognl表达式,所以在判断字符串sex变量是否是字符串Y的时候,
1.
<if test="signUpFlag=='Y'.toString()">

2.
<if test = 'signUpFlag== "Y"'>
注意:
不能使用
<if test="signUpFlag=='Y'">
and 1=1
</if>

因为mybatis会把'Y'解析为字符char类型,而不是String类型,不能做到判断的效果,java是强类型语言,所以不能这样写。

注意点:
mybatis中判断字符串为某一个值,必须+toString() 或者 flage=="xxx" (双引号),否则无法进入该判断
9月30
Supervisor(http://supervisord.org/)是用Python开发的一个client/server服务,是Linux/Unix系统下的一个进程管理工具,不支持Windows系统。它可以很方便的监听、启动、停止、重启一个或多个进程。用Supervisor管理的进程,当一个进程意外被杀死,supervisort监听到进程死后,会自动将它重新拉起,很方便的做到进程自动恢复的功能,不再需要自己写shell脚本来控制。

安装(pip安装)
pip安装supervisord

pip install supervisor
生成配置文件

echo_supervisord_conf > /etc/supervisord.conf
载入配置文件

supervisorctl  -c /etc/supervisord.conf
常用命令

supervisorctl stop program_name  # 停止某一个进程,program_name 为 [program:x] 里的 x
supervisorctl start program_name  # 启动某个进程
supervisorctl restart program_name  # 重启某个进程
supervisorctl stop groupworker:  # 结束所有属于名为 groupworker 这个分组的进程 (start,restart 同理)
supervisorctl stop groupworker:name1  # 结束 groupworker:name1 这个进程 (start,restart 同理)
supervisorctl stop all  # 停止全部进程,注:start、restartUnlinking stale socket /tmp/supervisor.sock
、stop 都不会载入最新的配置文件
supervisorctl reload  # 载入最新的配置文件,停止原有进程并按新的配置启动、管理所有进程
supervisorctl update  # 根据最新的配置文件,启动新配置或有改动的进程,配置没有改动的进程不会受影响而重启
安装(文件安装)
wget https://pypi.python.org/packages/31/7e/788fc6566211e77c395ea272058eb71299c65cc5e55b6214d479c6c2ec9a/supervisor-3.3.3.tar.gz#md5=0fe86dfec4e5c5d98324d24c4cf944bd

tar -zxvf supervisor-3.3.3.tar.gz
cd supervisor-3.3.3
python setup.py install


supervisor安装完成后会生成三个执行程序:supervisortd、supervisorctl、echo_supervisord_conf,分别是supervisor的守护进程服务(用于接收进程管理命令)、客户端(用于和守护进程通信,发送管理进程的指令)、生成初始配置文件程序。

添加应用
supervisord.conf 文件底部追加

[program:web]
command=/usr/bin/python /Users/qp/web/app.py
autostart=true
autorestart=false
stderr_logfile=/tmp/test_stderr.log
stdout_logfile=/tmp/test_stdout.log
问题
遇到“Another program is already listening on a port that one of our HTTP servers is configured to use.”这个报错是因为 Supervisor已经启动了,这个时候如果想要解决这个问题,最简单的方法自然是 kill 掉进程,然后重启。
$ ps aux | grep supervisord
qp               95808   0.0  0.0  4286732    744 s003  S+   10:22上午   0:00.01 grep supervisord
qp               95600   0.0  0.1  4303732   7656   ??  Ss   10:12上午   0:00.20 /usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/Resources/Python.app/Contents/MacOS/Python /usr/local/bin/supervisord -c /etc/supervisor.conf
$kill 95808 95600
http://127.0.0.1:9001 refused connection
supervisor.conf 修改如下


控制台输入supervisorctl,进入控制台时要输入的账号密码
[inet_http_server]         ; inet (TCP) server disabled by default
port=127.0.0.1:9001        ; ip_address:port specifier, *:port for all iface
username=user              ; default is no username (open server)
password=123               ; default is no password (open server)

[supervisorctl]
;serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL  for a unix socket
serverurl=http://127.0.0.1:9001



启动和停止服务示例如下

echo "${USER}" `date '+%Y%m%d-%H%M%S'`>> restart-rcms.log
supervisorctl stop rcms-auth
supervisorctl stop rcms-system
supervisorctl stop rcms-notice
supervisorctl stop rcms-business
supervisorctl stop rcms-workflow
supervisorctl stop rcms-xxljob
supervisorctl stop rcms-im
supervisorctl stop rcms-gateway

supervisorctl start rcms-auth
./wait-for-it.sh -t 120 localhost:19001
supervisorctl start rcms-system
supervisorctl start rcms-notice
supervisorctl start rcms-business
supervisorctl start rcms-workflow
supervisorctl start rcms-xxljob
supervisorctl start rcms-im
supervisorctl start rcms-gateway
9月24
解决方法
写入excel时使用 SXSSFWorkbook workbook = new SXSSFWorkbook(xssfWorkbook , 1000);只在内存中留1000行,不会占用过多的内存。下面只贴了部分代码。

public static void createExcelByTrade(List mergeCellConfigList ,  Map cellConfMap , List dataList ,String tempPath , String fileName  ) {
        try {
          int  excelRowNum  = 0;      
          short fontSize = 12;        
          // 创建新的Excel 工作簿
          XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
          SXSSFWorkbook workbook = new SXSSFWorkbook(xssfWorkbook , 1000);
                          
          Sheet sheet = workbook.createSheet(fileName);        
          // 设置合并表头        
          setMergeHeaderCellByTrade(   workbook,   sheet,    mergeCellConfigList ,  excelRowNum,   fontSize );
          excelRowNum ++ ;
          excelRowNum ++ ;
        
          //设置表头
          setHeaderCell(  workbook,   sheet,  cellConfMap ,  excelRowNum,   fontSize );
          excelRowNum ++ ;     //查询数据库中所有的数据  
          setCellData(   workbook,   sheet, cellConfMap,   dataList,   excelRowNum,   fontSize);                        
          // 新建一输出文件流
          FileOutputStream fOut = new FileOutputStream(tempPath);
          // 把相应的Excel 工作簿存盘
          workbook.write(fOut);
          //清空缓冲区数据
          fOut.flush();
          // 操作结束,关闭文件
          fOut.close();
          System.out.println("文件生成...");
        } catch (Exception e) {
            e.printStackTrace();
          System.out.println("已运行 xlCreate() : " + e);
        }
      }

9月23
一 、查看内存情况
#按 k 查看

free
点击在新窗口中浏览此图片
#按兆M查看

free -m


total:总计物理内存的大小。
used:已使用多大。
free:可用有多少。
Shared:多个进程共享的内存总额。
Buffers/cached:磁盘缓存的大小。
#所以空闲内存=free+buffers+cached=total-used
内存的使用情况
cat /proc/meminfo

查看进程的内存占用
pidstat -r -p 24427 1 5

内存占用高的前20
ps aux | head -1;ps aux |grep -v PID |sort -rn -k +4 | head -20

动态查看内存占用
slabtop

二 、问题定位
cached 占用过高问题
buffer,cached的作用:

cached主要负责缓存文件使用, 日志文件过大造成cached区内存增大把内存占用完 .
Free中的buffer和cache:(它们都是占用内存):
buffer : 作为buffer cache的内存,是块设备(磁盘)的缓冲区,包括读、写磁盘
cache: 作为page cache的内存, 文件系统的cache,包括读、写文件
如果 cache 的值很大,说明cache住的文件数很多。

linux服务器会自动释放内存,保障系统运行,但只会释放够用的内存,而不会去释放更多的内存。

解决方法:
手动释放cached方法有三种(系统默认值是0,释放之后你需要再改回0值):
释放前最好sync一下,防止丢数据

sync 在启动机器或关机之前一定要运行sync命令。记住在任何情况下,慎重地执行sync命令决不会有任何坏处,sync命令强制把磁盘缓冲的所有数据写入磁盘


To free pagecache: #echo 1 > /proc/sys/vm/drop_caches

To free dentries and inodes: #echo 2 > /proc/sys/vm/drop_caches

To free pagecache, dentries and inodes: #echo 3 > /proc/sys/vm/drop_caches

#常用方法是

sync

echo 1 > /proc/sys/vm/drop_caches

#清除后要还原系统默认配置:
echo 0 > /proc/sys/vm/drop_caches

#查看设置
sysctl -a | grep drop_caches
补充: echo 字符串 > 文件 就是把字符串内容从定向到文件中
点击在新窗口中浏览此图片

这时查看 free 可以看到 cached 降低了很多
9月8
   从WIN8升级到WIN10 ,Cisco AnyConnect Secure Mobility Client客户端不能使用,打开客户端,显示“The service provider in your current location is restricting access to the Internet. You need to log on with the service provider before you can establish a VPN session. You can try this by visiting any website with your browser.”
。打开网关地址登陆,也还是报这个错。卸载了重装 N次仍然如此。
设置中的  Message  History  显示如下:
[2015/9/8 14:38:24] Ready to connect.
[2015/9/8 14:38:31] Contacting **.**.**.**
[2015/9/8 14:38:31] Please enter your username and password.
[2015/9/8 14:38:33] User credentials prompt cancelled.
[2015/9/8 14:38:33] Use a browser to gain access.

解决方法:
1、推荐安装最新的 Cisco anyconnect-win-3.1.10010  对WIN10支持比较好 下载地址:网盘链接: http://pan.baidu.com/s/1sjzIY1R 密码: g3cp
2、WIN+R 打开运行 , 输入“certmgr.msc”打开证书管理器, 将VPN网关的证书从“其他人”目录 拖至  受信任的根证书颁发机构。
点击在新窗口中浏览此图片
3、  打开客户端 应该就可以,客户端的  Block connections to untrusted servers 这个选项要去掉
点击在新窗口中浏览此图片

至此,连接都正常了。。。
9月1
Word模板引擎,基于Microsoft Word模板和数据生成新的文档,并且支持用户自定义函数,函数可以在Word模板的任何位置执行。

poi-tl是一个完全的Java类库,你可以非常方便的加入到你的Java项目中,核心API只需要一行代码:

XWPFTemplate template = XWPFTemplate.compile("~/file.docx").render(datas);
所有的标签都是以 {{ 开始,以 }} 结束。

{{template}} 文本

{{@template}} 图片

{{#template}} 表格

{{*template}} 列表

{{+template}} Word文档合并

{{?template}}{{/template}} if和foreach功能

示例

从一个超级简单的例子开始:把{{title}}替换成"Poi-tl 模板引擎"。

新建文档template.docx,包含文本{{title}}
TDO模式:Template + data-model = output
//一行代码
XWPFTemplate template = XWPFTemplate.compile("~/template.docx").render(new HashMap(){{
        put("title", "Poi-tl 模板引擎");
}});
template.writeToFile("out_template.docx");

操作手册:http://deepoove.com/poi-tl/
Tags:
9月1
现实企业级Java应用开发、维护中,有时候我们会碰到下面这些问题:

OutOfMemoryError,内存不足

内存泄露

线程死锁

锁争用(Lock Contention)

Java进程消耗CPU过高

......

    这些问题在日常开发、维护中可能被很多人忽视(比如有的人遇到上面的问题只是重启服务器或者调大内存,而不会深究问题根源),但能够理解并解决这些问题是Java程序员进阶的必备要求。本文将对一些常用的JVM性能调优监控工具进行介绍,希望能起抛砖引玉之用。

而且这些监控、调优工具的使用,无论你是运维、开发、测试,都是必须掌握的。

A、 jps(Java Virtual Machine Process Status Tool)      

    jps主要用来输出JVM中运行的进程状态信息。语法格式如下:

jps [options] [hostid]
    如果不指定hostid就默认为当前主机或服务器。

    命令行参数选项说明如下:

-q 不输出类名、Jar名和传入main方法的参数

-m 输出传入main方法的参数

-l 输出main类或Jar的全限名

-v 输出传入JVM的参数
   比如下面:

root@ubuntu:/# jps -m -l
2458 org.artifactory.standalone.main.Main /usr/local/artifactory-2.2.5/etc/jetty.xml
29920 com.sun.tools.hat.Main -port 9998 /tmp/dump.dat
3149 org.apache.catalina.startup.Bootstrap start
30972 sun.tools.jps.Jps -m -l
8247 org.apache.catalina.startup.Bootstrap start
25687 com.sun.tools.hat.Main -port 9999 dump.dat
21711 mrf-center.jar
B、 jstack

    jstack主要用来查看某个Java进程内的线程堆栈信息。语法格式如下:

jstack [option] pid
jstack [option] executable core
jstack [option] [server-id@]remote-hostname-or-ip
    命令行参数选项说明如下:

-l long listings,会打印出额外的锁信息,在发生死锁时可以用jstack -l pid来观察锁持有情况-m mixed mode,不仅会输出Java堆栈信息,还会输出C/C++堆栈信息(比如Native方法)
    jstack可以定位到线程堆栈,根据堆栈信息我们可以定位到具体代码,所以它在JVM性能调优中使用得非常多。下面我们来一个实例找出某个Java进程中最耗费CPU的Java线程并定位堆栈信息,用到的命令有ps、top、printf、jstack、grep。
Tags: , , , , ,
分页: 13/67 第一页 上页 8 9 10 11 12 13 14 15 16 17 下页 最后页 [ 显示模式: 摘要 | 列表 ]