job定时任务介绍
【使用场景】当客户在使用数据库过程中,如果白天执行一些耗时比较长的任务(例如:统计数据汇总之类或从其他数据库同步数据的任务),会对正常的业务有性能影响,所以客户经常选择在晚上执行,无形中增加了客户的工作量。因此数据库兼容Orcale数据库中定时任务的功能,可以由客户创建定时任务,当任务时间点到达后可以自动触发任务的执行,从而可以减少客户运维的工作量。同时当我们执行一些SQL的实时性不是很高,集群资源又比较紧张的情况下,可以使用定时任务的方式下发SQL。
【定时任务的创建及管理】
可以参考官方文档进行操作:
https://support.huaweicloud.com/devg-dws/dws_04_0041.html
【常用视图介绍】我们经常通过pg_job这个系统表来查看定时任务的执行状态
pg_job中的字段如下:
job_id:作业ID。
current_postgres_pid:如果当前任务正在执行,那么此处记录运行此任务的postgres线程ID。默认为-1,表示此任务未被执行或已经执行结束。
log_user:创建者的UserName。
priv_user:作业执行者的UserName。
dbname:标识作业执行的数据库名。
node_name:标识当前作业是在哪个CN上创建和执行。
job_status:当前任务的执行状态,取值范围:('r', 's', 'f', 'd'),默认为's',取值含义:
- r=running
- s=successfully finished
- f=job failed
- d=disable
ps:当job连续执行失败16次,会将job_status自动设置为失效状态'd',后续不再执行该job。
start_date:作业第一次开始执行时间,时间精确到毫秒。
next_run_date:下次定时执行任务的时间,时间精确到毫秒。
failure_count:失败计数,作业连续执行失败16次,不再继续执行。
interval:作业执行的重复时间间隔。
last_start_date:上次运行开始时间,时间精确到毫秒。
last_end_date:上次运行的结束时间,时间精确到毫秒。
last_suc_date:上次成功运行的开始时间,时间精确到毫秒。
this_run_date:正在运行任务的开始时间,时间精确到毫秒。
nspname:作业运行时所在的命名空间的名称。
what:作业内容。
【任务状态判断】
job任务状态主要通过job_status来判断其当前状态,通过interval和next_run_date判断下次是否继续执行,其总体流程如下:
状态一:当时间到达job任务的next_run_date时间,job任务会进入任务队列,单个cn的job并发上限受到job_queue_processes的 限制,默认为10,超出该限制的任务会进行排队,此时job_status即任务的状态为f,start_date为创建job时传入的开始时间参数,start_date和next_run_date的值都为空,this_run_date的值也为空(当开始执行时该字段会进行刷新)。
可以通过如下SQL筛选处于该状态的job:select * from pg_job where job_status='f' and this_run_date is null;
状态二:当job排到队开始执行时,job_status即任务的状态会刷新为r,current_postgres_pid刷新为运行此任务的postgres线程ID,start_date和this_run_date会刷新为当前时间,若下次不执行next_run_date刷新为'4000-01-01 00:00:00',若下次继续执行则next_run_date刷新为下一次执行的时间。
可以通过如下SQL筛选处于该状态的job:select * from pg_job where job_status='r';
状态三:当前作业执行成功后若下一次继续执行则,job_status即任务的状态会刷新为s,failure_count连续失败次数置0,this_run_date会刷新为当前时间,若下次不执行next_run_date刷新为'4000-01-01 00:00:00',若下次继续执行则next_run_date刷新为下一次执行的时间。
可以通过如下SQL筛选处于该状态的job:select * from pg_job where job_status='s';
状态四:当前作业执行失败后后若下一次继续执行则,job_status即任务的状态会刷新为f,failure_count连续失败次数比之前加1,this_run_date会刷新为当前时间,若下次不执行next_run_date刷新为'4000-01-01 00:00:00',若下次继续执行则next_run_date刷新为下一次执行的时间。
可以通过如下SQL筛选处于该状态的job:select * from pg_job where job_status='f' and last_start_date is not null;
状态五:若作业上一次执行完后不继续执行,job_status即任务的状态会刷新为d,next_run_date刷新为'4000-01-01 00:00:00';
可以通过如下SQL筛选处于该状态的job:select * from pg_job where job_status='d';
状态六:作业线程启动时太慢被杀掉或者集群或者节点状态异常导致job线程丢失,此时作业的job_status为f 且last_end_date和last_suc_date为空,我们可以登录后台,搜索对应cn日志,zgrep 'job_id: xxx',在该日志文件中若找到如job worker with job id:xxx took too long time to start ,so canceled it
可以通过如下SQL筛选处于该状态的job:select * from pg_job where job_status='f' and;
【执行定时任务的常见场景】
在日志中查找cn日志是主要通过搜索关键字 job_id: xxx,(有些冒号后存在空格)
1.若根据job id查看对应cn日志出现如下报错:
error msg: canceling statement due to workload manager exception.
DETAIL: except rule [except_spill] is meet condition:rule [spillsize] is over limit, current value is:10517.
原因:该场景为下盘超过异常规则导致
规避措施:需要修改异规则:ALTER EXCEPT RULE 异常规则名 with (spollsize=xxx);
2.在客户端设置完任务,使用当前时间后job任务没有立即执行:
原因:当定时任务的执行时间设置为当前时间或者过去时间时,任务都会立即执行,这种场景可能是任务在排队等待,或者客户端和后台存在8小时时差,按照当前时间下发的任务需要等8小时后才会执行。
判断方法:针对上述场景我们可以通过select * from pg_job进行判断看该任务下次执行时间,和select now();数据库当前时间做比较判断是否在排队还是因为时差导致还没有到执行时间。
规避措施:
1)若为排队,我们可以根据集群资源使用情况判断是否调大job_queue_processes(需要重启集群),或者等待作业队列空闲
2)若为客户端和后台存在时差,可以调整定时任务开始时间进行规避
3.定时任务执行报错:all 32768 jobids have alloc, and there is no free jobid
原因:定时任务当前规格为最大32768个,当前已达到上限从而触发报错
规避措施:建议客户手动清理部分d状态的作业
select * from pg_job where job_status = 'd' and last_start_date < 'xxxxx' and interval = 'null'; --xxx为 清理最后一次执行为某天前的定时任务
call dbms_job.remove(xxx); --xxx 为定时任务的jobid
- 点赞
- 收藏
- 关注作者
评论(0)