掘金 后端 ( ) • 2024-05-08 10:52

达梦数据库国产化记录

背景说明

最近项目都是需要国产化,刚好用到的数据库就是达梦数据库,大同小异和mysql,就是很多东西需要适配语法,而且没有那么多资料可以去翻阅,官网就是观望。。。。,所以很多情况都是需要自己填坑,如果有付费的数据库就还好,有达梦的技术人员支持,排查起来比较快和简单。刚好我遇到的就是后者,嘿嘿。好了好了,不扯那么多了。回归正题,生产环境出现的情况是业务小高峰就是整个加载巨慢,或许很多人会说这时候就该用redis等分布式中间件去支撑应用,防爆数据库。实际上业务层面我们的前期做了redis,热点数据缓冲了。但是效果并不理想。还是在流量起来又卡又慢。。。这时候就需要我们去排查系统了

技术类型特征总结

用户态--cpu高负载低利用率-高io,io密集型

思路整理

0. os关键参数分析

我们对参数分析也是基于2个层级来划分,内核态和用户态。为啥基于这2个层级来划分是因为笔者过往涉及到内核态问题而非应用用户态导致,刚好本次是应用用户态应用引起的,故把它提出来。以便大家对问题进行分析,能够更加全面。如果还有其他思路欢迎大家pick我一下,共同进步

top
-   按 `1` 可以切换到单一 CPU 视图(显示每个 CPU 的详细信息)。
-   按 `M` 可以按内存使用率排序。
-   按 `P` 可以按 CPU 使用率排序。
cpu参数

什么是负载: 负载就是cpu在一段时间内正在处理以及等待cpu处理的进程数之和的统计信息,也就是cpu使用队列的长度统计信息,这个数字越小越好(如果超过CPU核心*0.7就是不正常)

分析是否是内核态线程占比过高导致。重点关注sys和iowait/si参数是否不断在变换,sys是内核态对于cpu的使用情况,而iowait这是针对io等待时间的使用情况,si的则是对于网络开销引起的软中断问题。这3个参数的异常变化足够判断了。 分析是否是用户态线程占比过高导致的,其实就是us就够了,us的就是直接可以通过top排序进行比对是否是我们自己的应用导致

lscpu 查看os具体的核数
top 结合lscpu的核数进行二次分析,
ps -aux 查看是否存在状态为`D`的进程,这个状态指的就是不可中断的睡眠状态的进程。处于这个状态的进程无法终止,也无法自行退出,只能通过恢复其依赖的资源或者重启系统来解决

image.png

通过sys和wa,si值得判断,都是处于低水平状态,故而推断不是os本身内核线程作祟,只能是用户态进程问题,dm进程 image.png

不存在僵尸进程(状态为 Z)和停止的进程(状态为 T),只有一个S的达梦进程在作妖

ps aux 
常见的进程状态及其说明:

1.  **R (Running)** :进程正在运行或者可运行,即在运行队列中。
1.  **S (Sleeping)** :进程正在睡眠,等待某个事件完成。大部分进程的大部分时间都是这种状态。
1.  **D (Disk Sleep)** :不可中断的睡眠状态,通常是在进行 I/O 操作。
1.  **T (Traced/Stopped)** :进程被停止,通常是因为收到 SIGSTOP 或 SIGTSTP 信号。
1.  **W (Swapped)** :进程被交换到磁盘,通常是因为内存不足。
1.  **X (Dead)** :进程已经结束,但进程描述符还存在,直到父进程调用 `wait` 或 `waitpid`。
1.  **Z (Zombie)** :僵尸进程,结束的进程且父进程未调用 `wait` 或 `waitpid` 来读取其终止状态。
1.  **N (Not runnable)** :进程已被调度,但尚未开始执行。

image.png

  • 反面教材就是这个样子,但是我们没有遇到

症状一 cpu高占比,低利用率

高占比其实就是高负载,高负载不是说压力大,是说明队列多,队列里面的任务有io的,cpu的,或者其他的,结合top各个cpu的利用率可以看出,利用率真的很低,只有一个cpu核用的比较大,处于50%。

1108f70567e7b4a328db7e7f0a74af2.png

image.png

查看达梦进程的线程使用情况

ps -L -p 1989213

## 参数说莫
`TIME`:这个字段显示了进程自启动以来累计使用的 CPU 时间

image.png

内存参数

关注swap交换空间,简单来说就是os的空间基本是稳定,大差不差的。如果used不断一直在交换,那就是内核态处于紧态,需要扩容了 需要格外说明的是,磁盘不断交换才是最核心的需要处理关键,如果是内存不断也失效的话是swap需要关注。

Swap空间的作用可简单描述为:当系统的物理内存不够用的时候,就需要将物理内存中的一部分空间释放出来,以供当前运行的程序使用。具体的请百度

ps aux --sort=-%mem 按照内存使用率的高低排序进程列表,如果有某个进程内存占用持续增加,可能存在内存泄漏的情况。

明显内存情况也是dm进程导致的,累计使用情况,50%左右和我们业务峰的load平均情况也是一致,结合top的used情况,内存不足排除 image.png

image.png

症状二 磁盘读写比低下

io读写参数
工具 -- dd

工具的话可以参考文章,站内跳转吧

dd if=/dev/zero of=test bs=8k count=4k oflag=dsync

a.测试磁盘的IO写速度
dd if=/dev/zero of=test bs=8k count=4k oflag=dsync
    time dd if=/dev/zero of=test.dbf bs=8k count=300000   如果要测试实际速度 还要在末尾加上 oflag=direct测到的才是真实的IO速度

b.测试磁盘的IO读速度
   time dd if=test bs=8k count=300000 of=/dev/null 

   #表示 每次写入/读取8k的数据,执行300000次


                        
bs=<字节数>:将ibs(输入)与欧巴桑(输出)设成指定的字节数;
cbs=<字节数>:转换时,每次只转换指定的字节数;
conv=<关键字>:指定文件转换的方式;
count=<区块数>:仅读取指定的区块数;
ibs=<字节数>:每次读取的字节数;
obs=<字节数>:每次输出的字节数;
of=<文件>:输出到文件;
seek=<区块数>:一开始输出时,跳过指定的区块数;
skip=<区块数>:一开始读取时,跳过指定的区块数;
--help:帮助;
--version:显示版本信息。
使用dsync/sync,dd会从/dev/zero中,每次读取4Kbytes数据,然后直接写入到硬盘当中,重复此步骤,直到共读取并且写入了1G的数据。

使用fdatasync/fsync,dd会从/dev/zero中一次性读取1G的数据,写入到磁盘的缓存中,然后再从磁盘缓存中读取,一次性写入到硬盘当中。

执行之后结果很明显了,io写入那么慢,是磁盘io问题

image.png

工具 -- iostat
iostat -x 1 10

如果 iostat 没有,要 yum install sysstat安装这个包,如果%util接近100%,表明I/O请求太多,I/O系统已经满负荷,磁盘可能存在瓶颈,一般%util大于70%,I/O压力就比较大,读取速度有较多的wait,然后再看其他的参数

image.png

1. 数据库参数分析

达梦是单进程多线程模型设计(这是网上查的,官网没有找到,有待商榷),但是通过查看pid的信息,确实也论证了这个观点。所以cpu利用率不高也就好解释了,即使系统目前的情况是16核64g的单机服务器。

    pstree -p 1989213
    ps -L -p 1989213

image.png

综合os的情况后对比

结合os的情况,cpu属于负载高,利用率低下,io磁盘读写慢。 可以看出我们问题就是io读写阻塞导致的。现在排查方向就是慢sql,死锁,针对db实例进行针对性优化即可

数据量情况

根据db同学给我信息来看的话,我们的数据特征是大量的静默冷数据躺着。但是,又是存在局部热点数据徒增的烦恼。做过GIS的应用都是知道的,轨迹数据是整个系统最重要的数据也是最重要的资源,同时也是系统io瓶颈。 如下,我们可以看出单表都是几十gb起步的,同时很多都是类似历史冷数据,不能丢同时必须要存库,偶尔还要请求一下,对于db实例来说,简直是灾难。。。

# 大表展示

gis系统作业表(数据量:94909944 数据大小:29.16GB)  
gis系统状态表(数据量:603780803 数据大小:106.67GB)  
gis系统轨迹表(数据量:54938833 数据大小:29.43GB)  
gis系统轨迹历史表(数据量:344611512 数据大小:169.17GB)  
gis系统轨迹备份回归表(数据量:346240097 数据大小:204.74GB)


通过和db同学一起薅头发之后,几亿条数据,单表完全不可能撑得住,同时又不能采用第三方中间件进行支持,扩容吃流量,只能薅达梦实例的能力了,db同学灵光一闪,说采用表空间来切割,我以前是没用过,所以一脸懵逼,但是,通过伟大的kimi,简单入门,给出定义---数据分片瞬间懂了

慢sql情况

这种就是看业务情况优化了

SELECT * FROM (  
SELECT distinct SESS_ID,SQL_TEXT,DATEDIFF(SS,LAST_SEND_TIME,SYSDATE) SS,   
SF_GET_SESSION_SQL(SESS_ID) FULLSQL  
FROM V$SESSIONS WHERE STATE='ACTIVE')  
WHERE SS>=1;

1548539d4befe301f0145f51acbb95e.png

死锁情况

这种是分布式定时任务引起的,查看另外一个文章

select distinct c.* from v$lock a  
left join sysobjects b on b.ID=a.TABLE_ID  
left join v$sessions c on a.TRX_ID=c.TRX_ID  
--where c.sql_text like '%XXL_JOB_GROUP%'  
where a.BLOCKED=1

企业微信截图_17134084751303.png

实战操作

表分区

不在MAIN主空间操作,而是按照业务维度进行分区如下

image.png

收集信息统计工具

该工具是达梦独有的,简单来说就是启一个数据库实例任务,不断的收集sql增长情况,然后自动添加类似索引的辅助索引,加速请求,具体的解释需要等达梦论坛。实际情况是加了这个任务之后,确实加速了在业务响应速度上

SP_INIT_JOB_SYS(1);        ----此语句如果报错,对象[SYSMAILINFO]已存在 等信息忽略就行,说明系统作业已经开启不影响
call SP_CREATE_JOB('statistics',1,0,'',0,0,'',0,'');
call SP_JOB_CONFIG_START('statistics');
call SP_ADD_JOB_STEP('statistics', 'statistics1', 0, 'begin
for rs in (select ''sf_set_SESSION_para_value(''''HAGR_HASH_SIZE'''',(select cast(
case when max(table_rowcount(owner,table_name))<=(select max_value from v$dm_ini 
where para_Name=''''HAGR_HASH_SIZE'''') and max(table_rowcount(owner,table_name))>=(
select min_value from v$dm_ini where para_Name=''''HAGR_HASH_SIZE'''')  then 
max(table_rowcount(owner,table_name)) when max(table_rowcount(owner,table_name))<(
select min_value from v$dm_ini where para_Name=''''HAGR_HASH_SIZE'''') then
 (select min_value from v$dm_ini where para_Name=''''HAGR_HASH_SIZE'''') else 
 (select max_value from v$dm_ini where para_Name=''''HAGR_HASH_SIZE'''') end as bigint) 
 from dba_tables where owner=''''''||NAME||''''''));''
sql1,''DBMS_STATS.GATHER_SCHEMA_STATS(''''''||NAME||'''''',100,TRUE,''''FOR ALL COLUMNS SIZE AUTO'''');'' 
sql2
 from SYS.SYSOBJECTS where TYPE$=''SCH'' ) loop
execute  immediate rs.sql1;
execute  immediate rs.sql2;
end loop;
end;', 0, 0, 0, 0, NULL, 0);
call SP_ADD_JOB_SCHEDULE('statistics', 'statistics1', 1, 2, 1, 64, 0, '01:00:00', NULL, '2021-11-08 14:54:37', NULL, '');
call SP_JOB_CONFIG_COMMIT('statistics');

效果对比

sql优化

慢sql 和死锁现在是看不到了,基于ssd切换和表空间,表信息收集工具

hdd机械磁盘换成ssd硬盘

读写对比
  1. 之前

image.png

  1. 现在
# 写情况
time dd if=/dev/zero of=test bs=8k count=4k oflag=dsync
# 读情况
time dd if=test bs=8k count=300000 of=/dev/null 

image.png

image.png

cpu负载对比
  1. 之前 1108f70567e7b4a328db7e7f0a74af2.png
  2. 之后 image.png

总结

本次优化围绕达梦实例优化,整体排查下来,非os限制,而是磁盘瓶颈限制以及dm数据收集统计工具没有激活

参考内容

优秀博主

求文推荐

觉得文章对你有帮助,记得点赞收藏关注,一键三连