• [其他] 【告警】CPU使用率超过阈值
    【问题现象】  在前端FIM界面上观察集大部分节点的CPU使用率持续飚高,具体情况见下图:【问题分析】 1. 通过TOP命令查看gaussdb 进程的CPU使用率,可以观察到在CPU使用高峰的时候可以达到1000%+,当时截图没有保留,下图为示例。2. 使用 top -H -p pid查找进程内占用的CPU百分比较高的线程。3. 根据线程的PID找到对应的语句select * from pgxc_thread_wait_status t1, pgxc_stat_activity a1 where t1.query_id = a1.query_id and lwtid = xxxx ;通过上面的信息可以看到有两个长时间执行不完的查询语句导致的。【解决办法】临时将语句先kill 掉,观察集群CPU使用率明显下降。对于用户调试性的语句可以配置异常规则, 设置参数statement_timeout,执行超时的语句数据库会自动给杀掉。配置多租户,限制单个用户的CPU使用率,避免一个语句将所有CPU都消耗掉。
  • [技术干货] 从存储端高并发之线程池,聊聊GaussDB(for MySQL) 的高扩展性
  • [技术干货] 怎样安全地关闭MySQL实例
    分析了mysqld进程关闭的过程,以及如何安全、缓和地关闭MySQL实例,对这个过程不甚清楚的同学可以参考下。关闭过程:1、发起shutdown,发出  SIGTERM信号2、有必要的话,新建一个关闭线程(shutdown thread)如果是客户端发起的关闭,则会新建一个专用的关闭线程如果是直接收到 SIGTERM 信号进行关闭的话,专门负责信号处理的线程就会负责关闭工作,或者新建一个独立的线程负责这个事当无法创建独立的关闭线程时(例如内存不足),MySQL Server会发出类似下面的告警信息:Error: Can't create thread to kill server3、MySQL Server不再响应新的连接请求关闭TCP/IP网络监听,关闭Unix Socket等渠道4、逐渐关闭当前的连接、事务空闲连接,将立刻被终止;当前还有事务、SQL活动的连接,会将其标识为 killed,并定期检查其状态,以便下次检查时将其关闭;(参考 KILL 语法)当前有活跃事务的,该事物会被回滚,如果该事务中还修改了非事务表,则已经修改的数据无法回滚,可能只会完成部分变更;如果是Master/Slave复制场景里的Master,则对复制线程的处理过程和普通线程也是一样的;如果是Master/Slave复制场景里的Slave,则会依次关闭IO、SQL线程,如果这2个线程当前是活跃的,则也会加上 killed 标识,然后再关闭;Slave服务器上,SQL线程是允许直接停止当前的SQL操作的(为了避免复制问题),然后再关闭该线程;在MySQl 5.0.80及以前的版本里,如果SQL线程当时正好执行一个事务到中间,该事务会回滚;从5.0.81开始,则会等待所有的操作结束,除非用户发起KILL操作。当Slave的SQL线程对非事务表执行操作时被强制 KILL了,可能会导致Master、Slave数据不一致;5、MySQL Server进程关闭所有线程,关闭所有存储引擎;刷新所有表cache,关闭所有打开的表;每个存储引擎各自负责相关的关闭操作,例如MyISAM会刷新所有等待写入的操作;InnoDB会将buffer pool刷新到磁盘中(从MySQL 5.0.5开始,如果innodb_fast_shutdown不设置为 2 的话),把当前的LSN记录到表空间中,然后关闭所有的内部线程。6、MySQL Server进程退出关于KILL指令从5.0开始,KILL 支持指定  CONNECTION | QUERY两种可选项:KILL CONNECTION和原来的一样,停止回滚事务,关闭该线程连接,释放相关资源;KILL QUERY则只停止线程当前提交执行的操作,其他的保持不变;提交KILL操作后,该线程上会设置一个特殊的 kill标记位。通常需要一段时间后才能真正关闭线程,因为kill标记位只在特定的情况下才检查:1、执行SELECT查询时,在ORDER BY或GROUP BY循环中,每次读完一些行记录块后会检查 kill标记位,如果发现存在,该语句会终止;2、执行ALTER TABLE时,在从原始表中每读取一些行记录块后会检查 kill 标记位,如果发现存在,该语句会终止,删除临时表;3、执行UPDATE和DELETE时,每读取一些行记录块并且更新或删除后会检查 kill 标记位,如果发现存在,该语句会终止,回滚事务,若是在非事务表上的操作,则已发生变更的数据不会回滚;4、GET_LOCK() 函数返回NULL;5、INSERT DELAY线程会迅速内存中的新增记录,然后终止;6、如果当前线程持有表级锁,则会释放,并终止;7、如果线程的写操作调用在等待释放磁盘空间,则会直接抛出“磁盘空间满”错误,然后终止;8、当MyISAM表在执行REPAIR TABLE 或 OPTIMIZE TABLE 时被 KILL的话,会导致该表损坏不可用,指导再次修复完成。安全关闭MySQL几点建议想要安全关闭 mysqld 服务进程,建议按照下面的步骤来进行:0、用具有SUPER、ALL等最高权限的账号连接MySQL,最好是用 unix socket 方式连接;1、在5.0及以上版本,设置innodb_fast_shutdown = 1,允许快速关闭InnoDB(不进行full purge、insert buffer merge),如果是为了升级或者降级MySQL版本,则不要设置;2、设置innodb_max_dirty_pages_pct = 0,让InnoDB把所有脏页都刷新到磁盘中去;3、设置max_connections和max_user_connections为1,也就最后除了自己当前的连接外,不允许再有新的连接创建;4、关闭所有不活跃的线程,也就是状态为Sleep  且 Time 大于 1 的线程ID;5、执行 SHOW PROCESSLIST  确认是否还有活跃的线程,尤其是会产生表锁的线程,例如有大数据集的SELECT,或者大范围的UPDATE,或者执行DDL,都是要特别谨慎的;6、执行 SHOW ENGINE INNODB STATUS 确认History list length的值较低(一般要低于500),也就是未PURGE的事务很少,并且确认Log sequence number、Log flushed up to、Last checkpoint at三个状态的值一样,也就是所有的LSN都已经做过检查点了;7、然后执行FLUSH LOCKAL TABLES 操作,刷新所有 table cache,关闭已打开的表(LOCAL的作用是该操作不记录BINLOG);8、如果是SLAVE服务器,最好是先关闭 IO_THREAD,等待所有RELAY LOG都应用完后,再关闭 SQL_THREAD,避免 SQL_THREAD 在执行大事务被终止,耐心待其全部应用完毕,如果非要强制关闭的话,最好也等待大事务结束后再关闭SQL_THREAD;9、最后再执行 mysqladmin shutdown。10、紧急情况下,可以设置innodb_fast_shutdown = 1,然后直接执行 mysqladmin shutdown 即可,甚至直接在操作系统层调用 kill 或者 kill -9 杀掉 mysqld 进程(在innodb_flush_log_at_trx_commit = 0 的时候可能会丢失部分事务),不过mysqld进程再次启动时,会进行CRASH RECOVERY工作,需要有所权衡。啰嗦那么多,其实正常情况下执行 mysqladmin shutdown 就够了,如果发生阻塞,再参考上面的内容进行分析和解决吧,哈哈:)
  • [其他] 【OS】集群出现大量(5W+)僵尸进程,OS load高,引发os重启
    【问题现象】操作系统版本:Redhat 7.4 / x86GaussDB版本:GaussDB A 6.5.1.5集群出现大量(5W+)僵尸进程,OS load高,引发os重启,现场排查发现是后台的secbox反复在重启引发的该僵尸进程【问题分析】1、通过观察CMA的日志,发现secbox在不停的反复重启2、secbox重启时,会调用date命令,而secbox出错退出,这些date命令就会变成僵尸进程3、进一步调查secbox重启原因发现,该集群的mount信息中,对于/var/log/Bigdata这一级目录单独做了挂载:4、产品资料手册里面描述的,对于日志盘需要按照下列方式挂载:5、未按照4中描述方式挂载时,由于和secbox.conf内容不匹配,进而引发secbox反复重启。6、现场通过手动调整secbox.conf,增加如下列,进行规避【解决方案】由于OS的挂盘配置不当,导致secbox后台服务反复重启,引发大量僵尸进程,在业务高峰期时,僵尸进程积压,导致OS重启。现场通过手动调整secbox.conf,增加如下列,进行规避
  • [技术干货] [转载]Python 并发编程之线程锁
    线程 --> 锁1、锁与GILGIL 是python 解释器全局锁2、同步锁多个线程抢占资源的情况:from threading import Thread import os,time def work():     global n     temp=n     time.sleep(0.1)     n=temp-1 if __name__ == '__main__':     n=100     l=[]     for i in range(100):         p=Thread(target=work)         l.append(p)         p.start()     for p in l:         p.join()     print(n) #结果可能为99import threading R=threading.Lock() R.acquire() ''' 对公共数据的操作 '''同步锁的引用:from threading import Thread,Lock import os,time def work():     global n     lock.acquire()     temp=n     time.sleep(0.1)     n=temp-1     lock.release() if __name__ == '__main__':     lock=Lock()     n=100     l=[]     for i in range(100):         p=Thread(target=work)         l.append(p)         p.start()     for p in l:         p.join()     print(n) #结果肯定为0,由原来的并发执行变成串行,牺牲了执行效率保证了数据安全互斥锁与join的区别:#不加锁:并发执行,速度快,数据不安全 from threading import current_thread,Thread,Lock import os,time def task():     global n     print('%s is running' %current_thread().getName())     temp=n     time.sleep(0.5)     n=temp-1 if __name__ == '__main__':     n=100     lock=Lock()     threads=[]     start_time=time.time()     for i in range(100):         t=Thread(target=task)         threads.append(t)         t.start()     for t in threads:         t.join()     stop_time=time.time()     print('主:%s n:%s' %(stop_time-start_time,n)) ''' Thread-1 is running Thread-2 is running ...... Thread-100 is running 主:0.5216062068939209 n:99 ''' #不加锁:未加锁部分并发执行,加锁部分串行执行,速度慢,数据安全 from threading import current_thread,Thread,Lock import os,time def task():     #未加锁的代码并发运行     time.sleep(3)     print('%s start to run' %current_thread().getName())     global n     #加锁的代码串行运行     lock.acquire()     temp=n     time.sleep(0.5)     n=temp-1     lock.release() if __name__ == '__main__':     n=100     lock=Lock()     threads=[]     start_time=time.time()     for i in range(100):         t=Thread(target=task)         threads.append(t)         t.start()     for t in threads:         t.join()     stop_time=time.time()     print('主:%s n:%s' %(stop_time-start_time,n)) ''' Thread-1 is running Thread-2 is running ...... Thread-100 is running 主:53.294203758239746 n:0 ''' #有的同学可能有疑问:既然加锁会让运行变成串行,那么我在start之后立即使用join,就不用加锁了啊,也是串行的效果啊 #没错:在start之后立刻使用jion,肯定会将100个任务的执行变成串行,毫无疑问,最终n的结果也肯定是0,是安全的,但问题是 #start后立即join:任务内的所有代码都是串行执行的,而加锁,只是加锁的部分即修改共享数据的部分是串行的 #单从保证数据安全方面,二者都可以实现,但很明显是加锁的效率更高. from threading import current_thread,Thread,Lock import os,time def task():     time.sleep(3)     print('%s start to run' %current_thread().getName())     global n     temp=n     time.sleep(0.5)     n=temp-1 if __name__ == '__main__':     n=100     lock=Lock()     start_time=time.time()     for i in range(100):         t=Thread(target=task)         t.start()         t.join()     stop_time=time.time()     print('主:%s n:%s' %(stop_time-start_time,n)) ''' Thread-1 start to run Thread-2 start to run ...... Thread-100 start to run 主:350.6937336921692 n:0 #耗时是多么的恐怖 '''3、死锁与递归锁进程也有死锁与递归锁,在进程那里忘记说了,放到这里一切说了额所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程,如下就是死锁死锁:from threading import Lock as Lock import time mutexA=Lock() mutexA.acquire() mutexA.acquire() print(123) mutexA.release() mutexA.release()解决方法,递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁:递归锁:from threading import RLock as Lock import time mutexA=Lock() mutexA.acquire() mutexA.acquire() print(123) mutexA.release() mutexA.release()典型问题:科学家吃面死锁问题:import time from threading import Thread,Lock noodle_lock = Lock() fork_lock = Lock() def eat1(name):     noodle_lock.acquire()     print('%s 抢到了面条'%name)     fork_lock.acquire()     print('%s 抢到了叉子'%name)     print('%s 吃面'%name)     fork_lock.release()     noodle_lock.release() def eat2(name):     fork_lock.acquire()     print('%s 抢到了叉子' % name)     time.sleep(1)     noodle_lock.acquire()     print('%s 抢到了面条' % name)     print('%s 吃面' % name)     noodle_lock.release()     fork_lock.release() for name in ['哪吒','egon','yuan']:     t1 = Thread(target=eat1,args=(name,))     t2 = Thread(target=eat2,args=(name,))     t1.start()     t2.start()递归锁解决死锁问题:import time from threading import Thread,RLock fork_lock = noodle_lock = RLock() def eat1(name):     noodle_lock.acquire()     print('%s 抢到了面条'%name)     fork_lock.acquire()     print('%s 抢到了叉子'%name)     print('%s 吃面'%name)     fork_lock.release()     noodle_lock.release() def eat2(name):     fork_lock.acquire()     print('%s 抢到了叉子' % name)     time.sleep(1)     noodle_lock.acquire()     print('%s 抢到了面条' % name)     print('%s 吃面' % name)     noodle_lock.release()     fork_lock.release() for name in ['哪吒','egon','yuan']:     t1 = Thread(target=eat1,args=(name,))     t2 = Thread(target=eat2,args=(name,))     t1.start()     t2.start()
  • [其他] 【故障】ldapserver与krbserver进程故障。
    【问题现象】ldapserver与krbserver进程故障。产生ALM-12007告警。【分析过程】1.确认krb与ldap同时故障,krb依赖ldap,所以该问题实际为ldap故障。将范围圈定在ldap上。2.多节点环境,集群类型相同,操作系统一致,排除不同环境差异。3.执行ldd /usr/sbin/ldap,好坏节点结果一致。4.执行rpm -qa |grep ldap,好坏节点结果一致。5.至此确认环境无差异,推测为环境变量导致。【解决方案】重启失败节点的nodeagent进程。恢复被污染的环境变量。1.将失败节点的nodeagent kill掉。 2.重启一下nodeagent。切换到omm用户执行sh /opt/huawei/Bigdata/om-agent/nodeagent/bin/stop-agent.sh,注意不要source mppdb的环境变量。3.sh /opt/huawei/Bigdata/om-agent/nodeagent/bin/start-agent.sh4.重启后 再从界面启动下ldap实例。至此,问题解决。
  • [其他] 【OS】【CPU】CPU高的高效排查手段
    1.top看哪个进程高,记pid2.top -H -p pid 查看这个进程里具体什么线程占用cpu3.gstack pid(线程id),可以看下这个语句的执行过程,是在干些什么事情。4.连到数据库,查用线程的id,查pgxc_thread_wait_status,可以找到对应语句的query_id整改掉该问题语句即可(杀掉-重写)。附自己开发的一个cpu高语句抓取脚本,在cpu高的gaussdb节点,sh gs_getcputop.sh脚本即可附件直接下载,修改为sh格式linux下 执行dos2unix 脚本名之后即可使用。
  • [技术干货] 2020-09-09:裸写算法:两个线程轮流打印数字1-100。
    2020-09-09:裸写算法:两个线程轮流打印数字1-100。
  • [其他] 【故障】【内存】idle线程过多导致memory is temporarily unavailable
    问题现象:集群出现很多dn报内存不可用问题,导致大批作业中断。ERROR: dn_6217_6218 memory is temporarily unavailableDETAIL: Failed on request of size 54720 bytes under queryid 43341056.定位过程:1)分析内存视图pv_total_memory_detail,发现动态使用内存最大值dynamic_peak_memory 10675MB, 大于 max_dynamic_memory 10499,因此出现内存不足问题。2)动态内存主要有session使用的动态内存、多线程共享的动态内存和通信库使用内存组成     其中多线程共享的动态内存峰值 dynamic_peak_shrctx 926MB、通信库使用的内存峰值sctpcomm_peak_memory 801MB,而总的动态内存dynamic_peak_memory 10675MB,分析可知动态内存中主要由session占用达8948MB。 3)查看pv_session_memory_detail视图     select split_part(pv_session_memory_detail.sessid,'.',2),sum(totalsize),count(*) from pv_session_memory_detail group by split_part(pv_session_memory_detail.sessid,'.',2) order by sum(totalsize) desc;     查询后发现进程中存在千余session,单session使用内存最大不足900MB,但因session总量大,客户业务正在运行,使得占用的总值高。     查看dn /proc/pid/status信息,确认进程中含有1059线程,与pv_session_memory_detail相符。4)查看idle线程数量SELECT count(*) FROM pg_stat_activity WHERE state=’idle’;返回结果700+5)结论Dn中总共1000余线程,idle线程700+,idle线程过多,虽然有利于连接复用,但会持有过多资源。应急措施:清理idle线程。gsql -d postgres -p 25308 -c "clean connection to all for database xxx;"清理后,查看结果SELECT count(*) FROM pg_stat_activity WHERE state=’idle’;返回结果0查看pv_total_memory_detail视图,dynamic_used_memory 2G+,大幅下降。
  • [其他] 【6.5.1】【CM】集群重启后,备cm_server 进程down,cms无法启动,探秘!
    【集群版本】GaussDB A 6.5.1【问题描述】集群重启后,备cm_server 进程down,cms无法启动【机制说明】cm_server进程的启动是由cm_agent拉起,在cm_server的listen端口被占用时cm_agent会等待端口占用解除后自动拉起恢复;cm_server简称cms;cm_agent简称cma;【问题分析】1. 用户进行的DN guc参数修改,用户执行重启集群操作,发现集群有告警,集群有cms down现象2. 分析当前节点cma的日志发现,cm_server进程需要listen 的端口号被占用,导致无法拉起,日志如下:StartAndStop WARNING: port:25302 already in use. /proc/net/tcp:  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode  14: 7C04240B:62D6 00000000:0000 0A 00000000:00000801 02:00000011 00000000  2000        0 197292192 2 ffff88017c952580 100 0 0 10 03. 进一步分析,发现是gs_check占用了此listen端口,通过kill掉gs_check进程,cm_server进程顺利恢复 netstat -anpo| grep 25302 kill -9  23666 kill后cms恢复正常。【问题根因】cms的进程listen端口被其他进程占用,导致cms无法被拉起【触发条件】gs_check等其他进程占用cm_server listen端口时会触发。【恢复方案】kill 占用cm_server listen端口占用进程恢复cms进程。
  • [技术干货] python 监控logcat关键字
    本文主要介绍使用Python调用ADB命令实现实时监控logcat关键字的功能采用多进程,可同时监控多个设备,监控多个关键字。 需要配置ADB环境,具体配置就不多介绍,随便搜一下一大把,直接上代码通过一个全局变量控制开启和关闭监控功能, INSTRUCTION 用于根据指令获取对应的方法名import os, threading, datetime# 获取当前文件所在目录,拼接出LOG路径LOG_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "log")# 配置需要监控的关键字KEYWORDS = ["ANR ", "NullPointerException", "CRASH", "Force Closed"]# 控制开启和关闭STOP_LOGCAT = True# 指令对应具体操作INSTRUCTION = {"1": "filter_keywords","2": "stop_filter_keywords","3": "exit"}def filter_keywords():global STOP_LOGCATSTOP_LOGCAT = Falsedevices = get_devices()  # 先获取所有连接的设备print("开始监控关键字")for device in devices:t = threading.Thread(target=filter_keyword, args=(device,))t.start()def stop_filter_keywords():global STOP_LOGCATif STOP_LOGCAT:print("没有正在执行的任务\n")else:STOP_LOGCAT = Trueprint("正在停止关键字监控\n")监控关键字主函数,def filter_keyword(device):print("设备%s关键字监控已开启" % str(device))sub = logcat(device)with sub:for line in sub.stdout: # 子进程会持续输出日志,对子进程对象.stdout进行循环读取for key in KEYWORDS:if line.decode("utf-8").find(key) != -1: # stdout输出为字节类型,需要转码message = "设备:%s 检测到:%s\n" % (device, key)# 设备:192.168.56.104:5555 检测到:ANRpath = get_log_path("bugreport") # 根据时间创建文件夹bugreport(device, path)# 拉取完整日志压缩包到创建的文件夹内send_message(message) # 这里可以换成自己要做的事情,比如发送邮件或钉钉通知if STOP_LOGCAT:breakprint("设备%s关键字监控已停止" % str(device))sub.kill()  通过 subprocess.Popen 创建进程执行命令,持续输出日志到 stdout# logcat持续输出日志def logcat(device):command = "adb -s " + str(device) + " logcat -v time"sub = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)return sub获取所有已连接设备的方法,执行"adb devices"后输出如下,通过对命令执行拿到的字符串切割获取所有设备号以列表方式存储# 获取所有devicedef get_devices():command = "adb devices"res = os.popen(command).read()devices = []res = res.split("\n")for i in res:if i.endswith("device"):devices.append(i.split('\t')[0])return devices# 打包下载所有日志到当前目录def bugreport(device, path):os.chdir(path)# bugreport会下载日志到当前文件夹,所以需要先切换到已经创建的目录command = "adb -s " + str(device) + " bugreport"subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=-1)print("设备:%s 日志路径:%s" % (str(device), path))以  当前文件所在目录/年/月/日 格式获取日志路径,如果不存在自动创建# 获取日志存放路径,如果不存在则按日期创建def get_log_path(tag):year = datetime.datetime.now().strftime('%Y')month = datetime.datetime.now().strftime('%m')day = datetime.datetime.now().strftime('%d')path = os.path.join(LOG_PATH, tag, year, month, day)if not os.path.exists(path):os.makedirs(path)return path main函数,循环接收指令,根据接收的指令拿到方法名,并通过eval()方法执行。def main():while True:print("-" * 100)print("1:开启关键字监控\n2:停止关键字监控\n3:退出")print("-" * 100)instruction = str(input("\n\n请输入要进行的操作号:\n"))print("-" * 100)while instruction not in INSTRUCTION.keys():instruction = str(input("\n\n输入无效,请重新输入:"))if int(instruction) == 9:exit()  # TODO 退出前需要判断是否有正在执行的monkey任务和关键字监控任务eval(INSTRUCTION[str(instruction)] + "()")if __name__ == '__main__':main()代码分段之后有点凌乱,看不明白可以把代码复制到一个文件里捋一下就明白了这里只写了开启日志监控和关闭的方法,中间有些处理可以根据自己需要实现,比如检测到关键字之后除了拉取所有日志外,可以发送邮件、钉钉之类的通知,根据自己需要去实现。原创不易,感觉本文有用可以点个赞,谢谢!
  • [其他] 【集群恢复】Gauss DB某一节点文件描述符耗尽应急
    节点文件描述符耗尽可能引起GaussDB实例重启造成集群不可用,本文主要讨论如何快速恢复集群以及后续如何预防。以下图为例,文件由于文件描述符耗尽导致实例异常状态如下:前提:如何确定实例异常是由于文件描述符耗尽影响的呢?可以查看主dn对应日志是否有以下日志出现,如上图所示对应为6045为主实例(对端实例6046目前状态为standby promoting状态能够说明该实例故障之前为备实例,那么6045肯定为主实例)有以上日志出现可以继续按照以下步骤进行修复。1、集群现场修复:方案一:1)查看从备日志是否有以下报错:2)此场景下一般是由于从备wal槽位残留造成备机升主时连接从备失败,此时登录从备实例所在节点kill该实例即可。方案二:方案一修复失败的话可以考虑使用该方案1)确认从备实例pg_xlog与base/dummy_standby/是为空,若不为空的话可以手动将其移动到其他路径(该场景下基本都为空)2)手动停止处于standby promoting的实例:cm_ctl stop -n nodeId -D 实例目录3)kill原主实例(实例状态为need repair),登录该实例所在节点执行以下命令,让其升主:kill pid; sleep 4; gs_ctl notify -M primary -D2、文件描述符耗尽预防:1)查看并修改文件描述符大小(集群内每台机器都需要修改,防止其他节点也出现该问题)    cat /etc/sysctl.conf |grep file-max    fs.file-max = 65536002)定期观察文件描述符使用情况:    查看机器整体文件描述符使用情况:lsof -u omm|grep urandom| wc -l    查看具体进程文件描述符使用情况:lsof -p pid|grep urandom| wc -l (pid 通过ps -ux查看,只关注gaussdb进程即可)3)若监控到文件描述符使用达到90%左右在业务低峰期可以考虑手动kill该进程释放资源。
  • [其他] 【OS】【CPU】单节点CPU高?是不是很多getClientInfo进程
        GaussDB(DWS)可以支持很大并发的连接数量同时连接,有时候会出现资源利用率过高,节点上cpu使用率飙升的情况,本次介绍一种情况,当连接数过多的时候,可能有一个进程导致单个cn节点cpu高。【判断问题】    1.CPU使用率单节点很高。    2.当前是不是cn:    ps -ef | grep coo    如果有进程,那么就是cn    3.为什么CPU高:top 看是否有大量getClientInfo进程,有的话直接走到处理步骤【处理问题】在CPU高的节点执行:ps -ef | grep getClientInfo | awk '{print $2}' | xargs kill -9ps -ef | grep getClientInfo,找到对应文件路径,修改其中main函数为直接return.
  • 从存储端高并发之线程池,聊聊GaussDB(for MySQL) 的高扩展性
  • [技术干货] 2020-08-29:进程线程的区别,除了包含关系之外的一些区别,底层详细信息?
    2020-08-29:进程线程的区别,除了包含关系之外的一些区别,底层详细信息?
总条数:813 到第 页
上滑加载中