# Cursor:mutex X

# <mark: 第一次加班到5点(XXXXX)>

# AWR指示

2022年11月1日,内蒙古月初对账, 对账语句游标版本一度7000多, 稳定后也保持在3000多。过多的硬解析导致数据库Hung。

# 对账语句

SELECT sum( medfeesumamt ) AS medfeesumamt, sum( fundpaysumamt ) AS fundpaysumamt, sum( acctpay ) AS acctpay, sum( psncashpay ) AS cashPaymt, count( * ) AS pnum,
clroptins  FROM si_balance  WHERE orgcode ='P15062100636'  AND insutype = '310' AND clroptins = '150621' AND clrtype = '41' 
and opertime between  to_date(concat('20221001', '000000'), 'yyyyMMddHH24miss') and  to_date(concat('20221031', '235959'), 'yyyyMMddHH24miss')
GROUP BY clroptins
1
2
3
4

Version Count 版本高的原因许许多, 我整理了一些解决方式, 并对每种方式进行了说明。

# 1 jvm修改

这个问题介于服务器,数据库,部署平台和jar之间。我们直接定死参数即可。
添加jvm参数:-Duser.language=en -Duser.country=US -Dfile.encoding=UTF-8
头两个-D解决语言不一致问题,最后一个解决平台服务启动有乱码问题。
1
2
3

# 2 程序修改

对非字符串类型有null可能的属性直接赋个初始值
@ApiModelProperty(value = "税率")
@TableField("TAX")
private Double tax = 0.0;
1
2
3
4

# 2.1 更改具体字段更新策略(对于改不了的字段)

@TableField(value="CLOUDID",updateStrategy=FieldStrategy.NOT_NULL)
private Long cloudid;
1
2

# 3 数据库配置修改

-- 设置数据库10503事件, 解决变量重新分配大小的问题
alter system set events '10503  trace name context forever ,level 128';
1
2

# 4 Between... And...

在山东,吉林,沈阳oracle 12c版本上发现。如果between and 语句版本过高,使用如下方式。

-- JDBC的Bug,会导致TIMESTAMP/Date类型不匹配,to_date() 函数代替TIMESTAMP的传入
opertime >=to_date(:5 , 'yyyyMMdd') and opertime < to_date(:6 , 'yyyyMMdd') + 1
1
2

# 以上4个基本可以将SQL版本数降到可控范围内

建议:
第一个必须配置,加入所有启动脚本。
第二个如果针对update..., 有超过500的进行配置。
第三个对有很多version高语句的进行配置, 配置后不用重启数据库。
第四个针对select...where 后面接between..and..日期类型。

# 数据库游标修改 (建议)

//查询当前游标使用数
select count(*) from v$open_cursor;

//查询游标信息
SELECT NAME, VALUE DISPLAY_VALUE, ISDEFAULT FROM V$PARAMETER WHERE NAME = 'open_cursors';

//修改游标数量
alter system set open_cursors = 2000;

//修改游标过时阈值
// oracle 12.2.0.1.0数据库参数_cursor_obsolete_threshold默认设置不合理导致大量等待事件cursor: mutex X
alter system set "_cursor_obsolete_threshold"=200 scope=spfile;

//启用优化器反馈可能会导致high version和cursor: pin S wait on X等待;以下执行计划Note里的基数反馈被使用也是因为开启了优化器反馈
alter system set "_optimizer_use_feedback"=false scope=spfile;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 自查语句


-- 查看版本号超过100的sql
SELECT S.LAST_ACTIVE_TIME,S.EXECUTIONS,S.SQL_ID, S.SQL_FULLTEXT,S.VERSION_COUNT,S.LAST_LOAD_TIME FROM v$sqlarea S WHERE VERSION_COUNT > 100 ORDER BY S.VERSION_COUNT DESC; 

-- 执行版本
SELECT SQL_TEXT,SQL_ID,LOADED_VERSIONS,OPEN_VERSIONS,EXECUTIONS,CHILD_NUMBER FROM V$sql WHERE sql_id='2cxwbyavstpj9';


-- 具体绑定变量
SELECT * FROM v$sql_bind_capture WHERE sql_id='2cxwbyavstpj9';
		
1
2
3
4
5
6
7
8
9
10
11

打个赏吧 点我,三毛五毛都是流水。