Greenplum的日志管理

本篇文档首先介绍GP的日志架构,日志工具的使用说明,然后介绍一下日志的定期清理配置案例

目录

Greenplum的日志管理

日志架构

日志路径

日志说明

日志常用的参数和配置方案

日志过滤工作的使用

检查segment日志

gplogfilter+gpssh工具组合在所有segment节点进行查找

查看时间段的

筛选

gp_toolkit.gp_log*

gp_toolkit.gp_log_* 视图

日志文件的定期清理


日志架构

日志路径

下面的表格展示了各种Greenplum数据库日志文件的位置。在文件路径中,date是YYYYMMDD格式的日期,instance是当前的实例名称,而n是Segment编号。

路径 描述
/home/gpadmin/gpadminlogs/* 很多不同种类的日志文件,每台服务器都有的目录
/home/gpadmin/gpadminlogs/gpstart_date.log 启动日志
/home/gpadmin/gpadminlogs/gpstop_date.log 停止日志
/home/gpadmin/gpadminlogs/gpsegstart.py_idb*gpadmin_date.log Segment启动日志
/home/gpadmin/gpadminlogs/gpsegstop.py_idb*gpadmin_date.log Segment停止日志
/greenplum/gpdata/master/gpseg-1/pg_log/startup.log 实例启动日志
/greenplum/gpdata/master/gpseg-1/gpperfmon/logs/gpmon.*.log gpperfmon日志
/greenplum/gpdata/mirror1/gpseg4/pg_log/*.csv 镜像Segment日志
/greenplum/gpdata/primary1/gpseg0/pg_log/*.csv 主Segment日志
/home/log/messages 全局Linux系统消息

服务器日志文件被写为逗号分隔值(CSV)格式。不是所有的日志项在所有的日志域中都有值。例如,只有与查询工作者进程相关的日志项才会有slice_id值。一个特定查询的相关日志项可以通过其会话标识符(gp_session_id)和命令标识符(gp_command_count)确定。

# 域名 数据类型 描述
1 event_time timestamp with time zone 日志项被写到日志中的时间
2 user_name varchar(100) 数据库用户名
3 database_name varchar(100) 数据库名
4 process_id varchar(10) 系统进程ID(带前缀“p”)
5 thread_id varchar(50) 线程计数(带前缀“th”)
6 remote_host varchar(100) 在Master上,是客户端机器的主机名/地址。在Segment上,是Master的主机名/地址。
7 remote_port varchar(10) Segment或Master的端口号
8 session_start_time timestamp with time zone 会话连接打开的时间
9 transaction_id int Master上的顶层事务ID。这个ID是任何子事务的父亲。
10 gp_session_id text 会话标识符号(带前缀“con”)
11 gp_command_count text 会话内部的命令编号(带前缀“cmd”)
12 gp_segment text Segment内容标识符(对主Segment带前缀“seg”,镜像Segment带前缀“mir”)。Master的内容id总是-1。
13 slice_id text 切片id(查询计划被执行的部分)
14 distr_tranx_id text 分布式事务ID
15 local_tranx_id text 本地事务ID
16 sub_tranx_id text 子事务ID
17 event_severity varchar(10) 值包括:LOG、ERROR、FATAL、PANIC、DEBUG1、DEBUG2
18 sql_state_code varchar(10) 与日志消息相关的SQL状态代码
19 event_message text 日志或者错误消息文本
20 event_detail text 与错误或者警告消息相关的详细消息文本
21 event_hint text 与错误或者警告消息相关的提示消息文本
22 internal_query text 内部产生的查询文本
23 internal_query_pos int 指向内部产生的查询文本中的光标
24 event_context text 产生消息的上下文
25 debug_query_string text 带有完整细节的用户提供的查询字符串,用于调试。这个字符串可能会由于内部使用而修改。
26 error_cursor_pos int 指向查询字符串中的光标
27 func_name text 产生这个消息的函数
28 file_name text 产生消息的内部代码文件
29 file_line int 产生消息的内部代码文件的行号
30 stack_trace text 与这个消息相关的栈跟踪文本

日志说明

1.3.1 pg_log

这个日志一般是记录服务器与DB的状态,比如各种Error信息,定位慢查询SQL,数据库的启动关闭信息,发生checkpoint过于频繁等的告警信息,诸如此类。linux自带的路径一般在/home/log/postgres下面。该日志有.csv格式和.log。个人建议用前一种,因为一般会按大小和时间自动切割,毕竟查看一个巨大的日志文件比查看不同时间段的多个日志要难得多。另外这种日志是可以被清理删除,压缩打包或者转移,同时并不影响DB的正常运行。当我们有遇到DB无法启动或者更改参数没有生效时,第一个想到的就是查看这个日志。

共有四类,FATAL-严重告警,ERROR-错误,WARNING-警告,LOG-操作日志。由于是文本文件所以查询检索很不方便,经过观察,发现这些文件是有固定格式的,可以采用外部表的方式进行查询,同时可以利用相关的工具进行过滤

1.3.2 pg_xlog

这个日志是记录的Postgresql的WAL信息,也就是一些事务日志信息(transaction log),默认单个大小是16M,源码安装的时候可以更改其大小。这些信息通常名字是类似'000000010000000000000013'这样的文件,这些日志会在定时回滚恢复(PITR),流复制(Replication Stream)以及归档时能被用到,这些日志是非常重要的,记录着数据库发生的各种事务信息,不得随意删除或者移动这类日志文件,不然你的数据库会有无法恢复的风险

当你的归档或者流复制发生异常的时候,事务日志会不断地生成,有可能会造成你的磁盘空间被塞满,最终导致DB挂掉或者起不来。遇到这种情况不用慌,可以先关闭归档或者流复制功能,备份pg_xlog日志到其他地方,但请不要删除。然后删除较早时间的的pg_xlog,有一定空间后再试着启动Postgres。

日志分析可用通过如下手段(这块内容我会单独整理一个blog)

  • 文件查看和检索

  • 利用外部表方式进行查询

  • 通过logstash工具进行定制分析

  • 通过在安装了gpperfmon组件的情况下,通过log_alert_history 进行查询

  • 查看系统视图

  1. List of relations

  2. Schema | Name | Type | Owner | Storage

  3. ------------+------------------------+------+----------+---------

  4. gp_toolkit | gp_log_command_timings | view | digoal | none -- 统计

  5. gp_toolkit | gp_log_database | view | digoal | none -- 这个包含当前数据库日志

  6. gp_toolkit | gp_log_master_concise | view | digoal | none -- 统计

  7. gp_toolkit | gp_log_system | view | digoal | none -- 这个包含所有日志

  8. (4 rows)

  • 通过gplogfilter工具来查找匹配指定标准的日志数据(包含segment gpssh)

1.3.3 pg_clog

pg_clog这个文件也是事务日志文件,但与pg_xlog不同的是它记录的是事务的元数据(metadata),这个日志告诉我们哪些事务完成了,哪些没有完成。这个日志文件一般非常小,但是重要性也是相当高,不得随意删除或者对其更改信息。

总结:

pg_log记录各种Error信息,以及服务器与DB的状态信息,可由用户随意更新删除

pg_xlog与pg_clog记录数据库的事务信息,不得随意删除更新,做物理备份时要记得备份着两个日志。

1.4 数据库的启动和关闭日志

程序日志文件:使用gpstart,gpstop 等相关命令的日志 缺省位于~/gpAdminLogs目录下 命令方式:<script_name>_.log 日志记录的格式: ::::[INFO|WARN|FATAL]:

日志常用的参数和配置方案

下面是Greenplum与安全相关的审计(或者日志)服务器配置参数,它们可以在postgresql.conf配置文件中设置:

域名 值范围 默认 描述
log_connections Boolean off 这会对服务器日志输出一行详细描述每个成功的连接。某些客户端程序(如psql)在决定是否要求口令时会尝试连接两次,因此重复的“connection received”消息并非总是表示问题。
log_disconnections Boolean off 在一个客户端会话终止时,这会在服务器日志中输出一行,其中会包括该会话的持续时间。
log_statement NONEDDLMODALL ALL 控制那些SQL语句会被记录。DDL记录所有数据定义命令,如CREATE、ALTER和DROP命令。MOD记录所有DDL语句外加INSERT、UPDATE、DELETE、TRUNCATE以及COPY FROM。如果PREPARE和EXPLAIN ANALYZE语句中如果包含有适当类型的命令,它们也会被日志记录。
log_hostname Boolean off 连接日志消息默认只显示连接主机的IP地址。把这个选项打开会导致主机名也被记录。注意这依赖于用户的主机名解析设置,而且这有可能会带来不可忽视的性能损失。
log_duration Boolean off 致使每一个满足log_statement的完成语句的持续时间被记录。
log_error_verbosity TERSEDEFAULTVERBOSE DEFAULT 为被记录的每条消息控制写入到服务器日志的细节多少。
log_min_duration_statement 毫秒数, 0, -1 -1 如果语句的持续时间大于等于指定的毫秒数,则在一个日志行中记录该语句和它的持续时间。将这个参数设置为0将打印出所有的语句及其持续时间。-1禁用这一特性。例如,如果用户将它设置为250,那么所有运行时间大于等于250ms的SQL语句将被记录。在跟踪应用中的未优化查询时,启用这一选项非常有用。
log_min_messages DEBUG5 DEBUG4 DEBUG3 DEBUG2 DEBUG1 INFO NOTICE WARNING ERROR LOG FATAL PANIC NOTICE 控制哪些消息级别会被写入到服务器日志。每个级别包括其后的所有级别。级别越靠后,发送到日志的消息就越少。
log_rotation_age 任意有效的时间表达式(数字和单位) 1d 决定个体日志文件的最大生存时间。在这个时间过去之后,一个新的日志文件将被创建。设置为零可禁用新日志文件基于时间创建。
log_statement_stats Boolean off 对每个查询,写入查询解析器、规划器和执行器的整体性能统计信息到服务器日志中。这是一种粗糙的画像手段。
og_truncate_on_rotation Boolean off 截断(重写)而不是追加到任何现存的同名日志文件。仅当一个新文件由于基于时间的轮转而被打开时,截断才会发生。例如,使用这个设置配合gpseg#-%H.log这样的log_filename会导致产生24个每小时的日志文件,然后循环地重写它们。关闭这一设置时,预先已经存在的文件在所有的情况下都会被追加内容。
       
       

如下一共三个配置方案,可根据业务需求进行配置

参数 说明
logging_collector 是否打印log
log_line_prefix 日志格式
log_directory 日志保存目录
log_statement 打印sql 类型
log_min_duration_statement *记录超时sql,超时多少秒记录*
*log日志方案(1)每天生成一个日志文件*  
log_filename = ‘postgresql-%Y-%m-%d_%H%M%S.log 文件名
log_truncate_on_rotation = off 文件存在是否覆盖
log_rotation_age = 1d 间隔多长时间更换新文件
log_rotation_size = 0 超过大小则换一个文件
log日志方案(2)每当日志写完一定大小,则换一个  
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log  
log_truncate_on_rotation = off  
log_rotation_age = 0  
log_rotation_size = 10M  
*log日志方案(3)只保留7天的日志,循环替换*  
log_filename = 'postgresql-%a.log 星期
log_truncate_on_rotation = on 开启覆盖
log_rotation_age = 1d  
log_rotation_size = 0  

日志过滤工作的使用

检查segment日志

 gplogfilter -n 3 输出最后3行日志如果想查看segment节点的日志,那么可以执行以下命令gpssh -f seg_hosts  #seg_hosts为segment节点的主机列表=>source /usr/local/greenplum-db/greenplum_path.sh=>gplogfilter -n 3 /greenplum/gpdata/primary1/gpseg*/pg_log/gpdb-*.csv  #segment节

gplogfilter+gpssh工具组合在所有segment节点进行查找

可以通过gplogfilter+gpssh组合使用,集中查看log

日志文件对于确定出错的原因可以提供更多的信息。 Master和每个Segment Instance都有自己的日志文件,它位于数据目录下的 pg_log 中。 Master 的日志文件包含着最多的信息,应该总是首先检查Master日志文件。

可以使用 gplogfilter命令 检查GPDB日志文件。要检查 Segment 的日志文件,可以使用 gpssh 在 Segment 主机上运行 gplogfilter命令

  • 检查日志文件

  1. 检查 Master 日志文件 WARNING、 ERROR、 FATAL 或 PANIC 级别的日志信息:

 $ gplogfilter -t
  1. 使用 gpssh 检查 Segment Instance 日志文件的 WARNING、 ERROR、 FATAL 或 PANIC级别日志信息:

 $ gpssh -f seg_hosts_file -e 'source /usr/local/greenplum   db/greenplum_path.sh;gplogfilter -t /data1/primary/*/pg_log/gpdb*.log' > seglog.out

查看时间段的

gplogfilter -b '2013-05-23 14:33' -e '2013-05-23 14:33'

筛选

 -f '<string>' | --find='<string>' ​Finds the log entries containing the specified string. ​-F '<string>' | --nofind='<string>' ​Rejects the log entries containing the specified string.-m <regex> | --match=<regex> ​Finds log entries that match the specified Python regular expression. See http://docs.python.org/library/re.html for Python regular expression syntax. ​​-M <regex> | --nomatch=<regex> ​Rejects log entries that match the specified Python regular expression. See http://docs.python.org/library/re.html for Python regular expression syntax. 

Greenplum提供了gp_toolkit.gp_log...视图,用来汇聚日志,方便查看。

gp_toolkit.gp_log*

由于GP为分布式数据库,当查看它的一些日志时,如果到服务器上查看,会非常的繁琐,而且不好排查问题。

Greenplum提供了gp_toolkit.gp_log...视图,用来汇聚日志,方便查看。

 [gpadmin@mdw ~]$ psqlpsql (8.3.23)Type "help" for help.​archdata=# \dv gp_toolkit.gp_log*  List of relationsSchema   |          Name          | Type |  Owner  | Storage ------------+------------------------+------+---------+---------gp_toolkit | gp_log_command_timings | view | gpadmin | nonegp_toolkit | gp_log_database        | view | gpadmin | nonegp_toolkit | gp_log_master_concise  | view | gpadmin | nonegp_toolkit | gp_log_system          | view | gpadmin | none(4 rows)​archdata=# 

gp_toolkit.gp_log_* 视图

  • gp_log_command_timings (只输出会话,PID,时间,如果关注运行较长时间的详细信息,可根据会话,PID在gp_log_system中定位)

 This view uses an external table to read the log files on the master and report the execution time of SQL commands executed in a database session.   The use of this view requires superuser permissions.  
  • gp_log_master_concise (只有master节点的日志)

 This view uses an external table to read a subset of the log fields from the master log file.   The use of this view requires superuser permissions.  
  • gp_log_system (汇聚master,segment,mirror节点的日志,含所有数据库)

 This view uses an external table to read the server log files of the entire Greenplum system (master, segments, and mirrors) and lists all log entries.   Associated log entries can be identified by the session id (logsession) and command id (logcmdcount).   The use of this view requires superuser permissions.  
  • gp_log_database (汇聚master,segment,mirror节点的日志,含当前数据库)

 This view uses an external table to read the server log files of the entire Greenplum system (master, segments, and mirrors) and lists log entries associated with the current database.   Associated log entries can be identified by the session id (logsession) and command id (logcmdcount).   The use of this view requires superuser permissions.  
 archdata=# \xExpanded display is on.archdata=# select * from gp_toolkit.gp_log_database limit 1000; -[ RECORD 1 ]--+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------logtime        | 2020-04-21 14:37:45.293413+08loguser        | gpadminlogdatabase    | archdatalogpid         | p21318logthread      | th1795716992loghost        | ::1logport        | 22062logsessiontime | 2020-04-21 14:37:45+08logtransaction | 0logsession     | logcmdcount    | logsegment     | seg-1logslice       | logdistxact    | loglocalxact   | logsubxact     | logseverity    | FATALlogstate       | 57P03logmessage     | the database system is starting uplogdetail      | loghint        | logquery       | logquerypos    | logcontext     | logdebug       | logcursorpos   | 0logfunction    | logfile        | postmaster.clogline        | 2927logstack       | -[ RECORD 2 ]--+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------logtime        | 2020-04-21 14:37:46.311543+08loguser        | gpadminlogdatabase    | archdatalogpid         | p21349logthread      | th1795716992loghost        | ::1logport        | 22074logsessiontime | 2020-04-21 14:37:46+08logtransaction | 0logsession     | con5logcmdcount    | cmd1logsegment     | seg-1logslice       | logdistxact    | loglocalxact   | logsubxact     | sx1logseverity    | LOGlogstate       | 00000logmessage     | statement: BEGINlogdetail      | loghint        | logquery       | logquerypos    | logcontext     | logdebug       | BEGINlogcursorpos   | 0logfunction    | logfile        | postgres.clogline        | 1590logstack       | -[ RECORD 3 ]--+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------logtime        | 2020-04-21 14:37:46.311627+08loguser        | gpadminlogdatabase    | archdatalogpid         | p21349logthread      | th1795716992loghost        | ::1logport        | 22074logsessiontime | 2020-04-21 14:37:46+08logtransaction | 0logsession     | con5logcmdcount    | cmd2logsegment     | seg-1logslice       | logdistxact    | loglocalxact   | logsubxact     | sx1logseverity    | LOGlogstate       | 00000logmessage     | statement: SET CLIENT_MIN_MESSAGES='ERROR'logdetail      | loghint        | logquery       | logquerypos    | logcontext     | logdebug       | SET CLIENT_MIN_MESSAGES='ERROR'logcursorpos   | 0logfunction    | logfile        | postgres.clogline        | 1590logstack       | -[ RECORD 4 ]--+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------logtime        | 2020-04-21 14:37:46.311674+08loguser        | gpadminlogdatabase    | archdatalogpid         | p21349logthread      | th1795716992loghost        | ::1logport        | 22074logsessiontime | 2020-04-21 14:37:46+08logtransaction | 0logsession     | con5logcmdcount    | cmd3logsegment     | seg-1logslice       | logdistxact    | loglocalxact   | logsubxact     | sx1logseverity    | LOGlogstate       | 00000logmessage     | statement: COMMITlogdetail      | loghint        | logquery       | logquerypos    | logcontext     | logdebug       | COMMITlogcursorpos   | 0logfunction    | logfile        | postgres.clogline        | 1590logstack       | 
 select * from gp_toolkit.gp_log_command_timings order by logsession,logcmdcount limit 100;  ​archdata=# select * from gp_toolkit.gp_log_command_timings order by logsession,logcmdcount limit 100;-[ RECORD 1 ]------------------------------logsession  | con10logcmdcount | cmd1logdatabase | gpperfmonloguser     | gpmonlogpid      | p14674logtimemin  | 2020-04-25 07:03:54.693368+08logtimemax  | 2020-04-25 07:03:54.702078+08logduration | 00:00:00.00871-[ RECORD 2 ]------------------------------logsession  | con10logcmdcount | cmd1logdatabase | gpperfmonloguser     | gpmonlogpid      | p24290logtimemin  | 2020-04-25 08:38:59.935377+08logtimemax  | 2020-04-25 08:38:59.943972+08logduration | 00:00:00.008595​
 select * from gp_toolkit.gp_log_master_concise limit 1000;  archdata=# select * from gp_toolkit.gp_log_master_concise limit 1000; -[ RECORD 1 ]--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------logtime     | 2020-04-21 14:30:21.830595+08logdatabase | logsession  | logcmdcount | logseverity | LOGlogmessage  | TransitionToMasterOrMirrorless: initializing XLog startup

日志文件的定期清理

greenplum日志存放在pg_log下,master节点和每个segment节点都会有,格式为gpdb-YYYY-MM-DD_hhmmss.cs 需要我们定期清理

定期清理master节点的日志,保留最近8天的日志

find master日志目录 -type f -name "gpdb-*.csv" -ctime +8 -exec rm {} \;

Greenplum的日志管理相关推荐

  1. 码农技术炒股之路——配置管理器、日志管理器

    配置管理器和日志管理器是项目中最为独立的模块.我们可以很方便将其剥离出来供其他Python工程使用.文件的重点将是介绍Python单例和logging模块的使用.(转载请指明出于breaksoftwa ...

  2. Linux 日志管理(RHEL7)

    日志管理 系统和程序的日记本 记录系统,程序运行中发生的各种事件 通过查看日志,了解及排除故障 信息安全控制的依据 内核及系统日志 由系统服务rsyslog统一记录/管理 日志消息采用文本格式 主要记 ...

  3. mysql二进制日志管理_MYSQL二进制日志管理脚本

    MYSQL二进制日志管理脚本脚本原理是每小时对进行flush生成新的二进制日志,将二进制日志备份至NFS,并压缩存放:#!/bin/bash#Purpose:管理二进制日志,每小时刷新二进制日志,并将 ...

  4. KBMMW 的日志管理器

    kbmmw 4.82 最大的新特性就是增加了 日志管理器. 新的日志管理器实现了不同类型的日志.断言.异常处理.计时等功能. 首先.引用kbmMWLog.pas 单元后,系统就默认生成一个IkbmMW ...

  5. Kubernetes-基于EFK进行统一的日志管理

    1.统一日志管理的整体方案 通过应用和系统日志可以了解Kubernetes集群内所发生的事情,对于调试问题和监视集群活动来说日志非常有用.对于大部分的应用来说,都会具有某种日志机制.因此,大多数容器引 ...

  6. 日志管理之 Docker logs - 每天5分钟玩转 Docker 容器技术(87)

    高效的监控和日志管理对保持生产系统持续稳定地运行以及排查问题至关重要. 在微服务架构中,由于容器的数量众多以及快速变化的特性使得记录日志和监控变得越来越重要.考虑到容器短暂和不固定的生命周期,当我们需 ...

  7. linux系统中的日志管理

    Linux系统中的日志管理 1 实验环境 2 journald日志服务 2.1 journalctl命令的用法 2.2 用journald服务永久存放日志 3 rsyslog日志服务 3.1 自定义日 ...

  8. 《构建高可用Linux服务器 第3版》—— 1.4 Linux服务器的日志管理

    本节书摘来自华章出版社<构建高可用Linux服务器 第3版>一 书中的第1章,第1.4节,作者:余洪春 ,更多章节内容可以访问云栖社区"华章计算机"公众号查看. 1.4 ...

  9. 十、springboot注解式AOP(@Aspect)统一日志管理

    springboot注解式AOP(@Aspect)统一日志管理 简介 AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功 ...

最新文章

  1. SAP WM初阶LQ02报错 - Movement Type 901 for manual transfer orders does not exist -
  2. WORD页边距、行距、页码、页眉页脚
  3. 2018-2019-2 网络对抗技术 20165305 Exp6 信息搜集与漏洞扫描
  4. 21-while里的break简单用法
  5. 在实际项目中使用LiteDB NoSQL数据库
  6. zjnu1730 PIRAMIDA(字符串,模拟)
  7. 链表冒泡排序java_055-冒泡排序算法代码实现
  8. 怎么用jquery实现全选_经济薄弱,该怎么实现花园梦?用这些替代物降低养花成本...
  9. [转载] python 判断字符串是否包含另一个字符串_强烈推荐:Python字符串(string)方法整理(一)...
  10. Kotlin — 在一个项目中混用 Java 与 Kotlin(混合开发)
  11. Ps 初学者教程,如何在图片中创建新背景?
  12. 中文文字校对和文档对比合并开源工具调研
  13. jspservlet面试题经典
  14. qu32调音台说明书_Qu-32 数字调音台
  15. 财商大电影——10部可以锻炼财商思维…
  16. 华为平板鸿蒙操作系统,华为平板 MatePad Pro 来了!首搭鸿蒙系统,与电脑“花样”协同…...
  17. 日期抽象数据类型设计与实现作业总结
  18. 微信公众号文章采集工具,可采集文章文字内容信息及图片
  19. 谈谈“五级工程师和职业发展”的思考
  20. 哮喘病人小气道上皮细胞 (Asthma) Small airway epithelial cells 培养解决方案

热门文章

  1. 《软件测试的艺术》第六章 更高级别的测试
  2. 【课程设计】数据库:火车票管理系统
  3. 2011.3.12 (ULE)
  4. 推荐几个超实用的开源自动化测试框架
  5. onclick事件的基本操作
  6. 字符串拼接onclick函数
  7. JPEG 原理详细分析
  8. grafana+zabbix+maraidb离线安装配置-监控H3C交换机
  9. 推荐一些Android学习网站
  10. 刷脸支付代理一个月能赚多少?