有也许没因此过之调节窗口

发布时间:2018-11-15  栏目:NoSQL  评论:0 Comments

前言

点 mongodb
已经产生一段时间了,从同开始的未打听,到本早就慢慢适应之nosql领域的尖子,还是经验了过多曲折。
于进展数据库选型的上,许多口连续好以
mongodb和mysql、oracle做比,并总出一致拟好详尽的剖析结果。
但这种分析往往改变不了管理者(或是架构师)的裁定。因为反复以控制用某种技术之前,管理者可能已有了答案,而分析比则是为为决定更加笃定,更起因。
尽管是说法有点让人丧气,但具体中诚如此。

一目了然的凡,mongodb不是涉及项目数据库,不按照经典的”三只范式”,也没有说明关联、事务(直到最新的4.0版才促成)等民俗数据库的特性
然而mongodb自带的无schema、副本集、自动分片等力量得到了大气之赏识,而重值得一提的是数据库本身提供了大量的监督、分析工具命令,对运维管理提供了大死的便利性。

既说到了工具,本文要介绍的凡相同慢被mtools的家伙。在这段子内,笔者一直当组织线上数据库日志的搜集分析,由于尚未比好之工具支撑,每次的分析工作归根结底要投入大量底人工。
当这种景象下,mtools
就足以帮助于庞大提升效率,下面的篇幅开始介绍这家伙。

第一说明:如果无进入调试模式的说话,默认的调剂窗口如下:

mtools是什么

mtools 是出于MongoDB
官方工程师实现之同法工具集,可以生迅速的日记查询分析、统计功能,此外还支持本地集群部署管理,非常方便新手上。
github地址,该套工具非官方公司维护,仅由作者做起来源维护,目前型之换代频度并无赛,但都起大量之使用者。

mtools使用python编写得,可经过pipy网站 获取;
欠工具包含了以下几单至关重要组件

mlaunch
支撑快速搭建本地测试环境,可以是单机、副本集、分片集群。
mlogfilter
日志过滤组件,支持按日寻找慢查询、全表扫描操作,支持通过多个属性进行信息过滤,支持出口为JSON格式。
mplotqueries
支撑用日志分析结果转换为图形式,依赖让tkinter(python图形模块)、和matplotlib模块。
mlogvis
支撑将日志分析结果转换为一个独自的HTML页面,实现同mplotqueries同样的效力。

网上有关mtools的资料早已多,包括其官文档的证实还于详细,这里只有对工具的行使状况做简单介绍

图片 1

足开啊

开始前的备:

1. 简易集群管理

履行以下命令,可以启动一个单节点的mongod进程。

# mlaunch init --single
launching: "mongod" on port 27017

可对比单节点手工搭建

再度实施另外一个稍复杂点的一声令下:

# mlaunch init --sharded 2 --replicaset --nodes 3 --config 3 --csrs --mongos 3 --port 27050 --auth --username admin --password admin@2016 --auth-db admin 
launching: "mongod" on port 27053
launching: "mongod" on port 27054
launching: "mongod" on port 27055
launching: "mongod" on port 27056
launching: "mongod" on port 27057
launching: "mongod" on port 27058
launching: config server on port 27059
launching: config server on port 27060
launching: config server on port 27061
replica set 'configRepl' initialized.
replica set 'shard01' initialized.
replica set 'shard02' initialized.
launching: mongos on port 27050
launching: mongos on port 27051
launching: mongos on port 27052
adding shards. can take up to 30 seconds...
Username "admin", password "admin@2016"

啊?已经完结了一个复入本集分片集群的搭建!27050是打始端口,–sharded 2
意味着出星星点点单分片,–replicaset 表示启用副本集,
–config 3 –csrs 表示config 使用CSRS结构的3节点副本集,–auth
表示启用鉴权, –username –password
为初始化的用户,默认该用户将富有所有库的管理权限。
总体集群的架构使下图所示:
图片 2

可透过以下命令进行管理

]# mlaunch list
PROCESS PORT STATUS PID
()
mongos 27050 running 13017
mongos 27051 running 13059
mongos 27052 running 13093
()
config server 27059 running 12134
config server 27060 running 12217
config server 27061 running 12261
()
shard01
    primary 27053 running 12404
    secondary 27055 running 12559
    mongod 27054 running 12509
()
shard02
    secondary 27057 running 12793
    secondary 27058 running 12845
    mongod 27056 running 12697
()
()
 auth: "admin:admin@2016"

启航停

# mlaunch stop
sent signal 15 to 12 processes.
# mlaunch start
launching: config server on port 27059
...

即时是一定便宜的,可以比分布式集群搭建手记
这篇稿子所描述的流程,相比手工搭建,该工具而减掉几十倍增时间。

新建控制台程序DebugWindowDemo:

2. 日志统计

mloginfo 是一个用于做日志信息统计的家伙,输入以下命令:

# mloginfo mongo.log
     source: mongo.log
       host: MongoDB_1:10001
        start: 2018 May 18 16:33:11.692
        end: 2018 May 19 01:13:08.290
date format: iso8601-local
     length: 144480
     binary: mongod
    version: 3.4.10
    storage: wiredTiger

可以看日志的起止时间限制、主机端口、版本、数据库引擎等一律要信息。

连接数
当我们愿意检查客户端的连天数情况经常,可以推行以下命令:

# mloginfo mongo.log --connections
CONNECTIONS
     total opened: 14282
     total closed: 14358
    no unique IPs: 4
socket exceptions: 0
127.0.0.1 opened: 12886 closed: 12889
172.21.0.29 opened: 658 closed: 716
172.21.0.28 opened: 461 closed: 490
172.21.0.27 opened: 277 closed: 263

经过如此的信息,进一步认清是否是连接了载等异常情况。

事件统计
又或者,你指望统计有时某些事件之产生频次。

# mloginfo mongo.log --distinct
DISTINCT
   14358 end connection ... ( ... now open)
   14281 connection accepted from ... # ... ( ... now open)
   13075 received client metadata from ... :
    5340 Successfully authenticated as principal ... on
    1194 Use of the aggregate command without the 'cursor'
     338 build index on: ... properties:
     244 building index using bulk method; build may temporarily use up to ... megabytes of RAM
     234 ns: ... key: ... name:
     219 Refreshing chunks for collection ... based on version
     218 Refresh for collection ... took ... ms and found version
     179 Index ... :

慢查询
当工作问题浅析中,慢查询是太常见的题目。

# mloginfo mongo.log --queries --sort count
QUERIES
namespace                  operation      pattern                              count      min (ms)    max (ms)  mean (ms)    95%-ile (ms) sum (ms)
nsspace.StatisticsHour   find             {"$and": [{"recordTime": 1}]..}     22331      276       747          345          414.0            7720736
nsspace.StatisticsHour   getmore       {"aggregate": 1, "cursor": ...}]}    231          200      304          227          272.0             52587
dmspace.DeviceInfo      remove          {"_id": 1}                              109        205      1786          420          771.0            45860
cmspace.DeviceData     update          {"appId": 1, "deviceId": 1}          95          201      1802          431          824.5            40966
dmspace.TaskHistory    update          {"_id": 1}                                54          268      2643          692          2019.0          37413
nsspace.StatisticsDay     find              {"$and": [{"recordTime": 1}], ..}   31          201      348            241          345.0            7472

苟上面的一声令下,将显示有慢查询,并按照出现次数排序。

又开信息

# mloginfo mongo.log --restart
RESTARTS
   May 18 21:37:51 version 3.4.10
   May 18 21:48:33 version 3.4.10

透过检测还开信息,对系统潜在的故障进行评估分析。

合本集切换
相同,主备切换可能致一定之事体失败,需要定期监测。

# mloginfo mongo.log --rsstate
RSSTATE
date host state/message
()
May 18 21:48:53 172.21.0.29:10001 ARBITER
May 18 21:49:26 172.21.0.28:10001 SECONDARY

修改Program.cs 的代码为:

3. 日记过滤

mlogfilter是一个强大的日记过滤模块,相比linux
的grep/egrep的文件过滤,该零件可以对日记内容开展剖析,并遵照我们怀念使之结果开展过滤。

翻开过10s的慢操作

# mlogfilter mongo.log --slow 10000 --shorten 200
2018-05-18T21:49:04.069+0800 I REPL [ReplicationExecutor] Starting an election, since we've seen no PRIMARY in the past 10000ms
2018-05-18T21:50:22.988+0800 I COMMAND [conn31] command dmspace.fs.chunks appName: "Mong...quireCount: { w: 46 } }, oplog: { acquireCount: { w: 46 } } } protocol:op_command 10804ms
2018-05-18T21:50:22.988+0800 I COMMAND [conn44] command dmspace.DeviceInfo command: inse...quireCount: { w: 16 } }, oplog: { acquireCount: { w: 16 } } } protocol:op_command 10931ms
2018-05-18T21:50:22.988+0800 I COMMAND [conn157] command dmspace.Lwm2mDevice command...quireCount: { w: 16 } }, oplog: { acquireCount: { w: 16 } } } protocol:op_command 10762ms
2018-05-18T21:50:22.988+0800 I COMMAND [conn156] command dmspace.TaskHistory command: in...quireCount: { w: 16 } }, oplog: { acquireCount: { w: 16 } } } protocol:op_command 10927ms
2018-05-18T21:50:50.104+0800 I COMMAND [conn31] command dmspace.DeviceInfo appName: "Mon...quireCount: { w: 16 } }, oplog: { acquireCount: { w: 16 } } } protocol:op_command 10020ms
2018-05-18T21:50:51.203+0800 I COMMAND [conn156] command dmspace.fs.chunks command: inse...quireCount: { w: 51 } }, oplog: { acquireCount: { w: 51 } } } protocol:op_command 10823ms

翻开慢扫描操作
迟迟扫描是因该操作需要扫描过多的笔录(超过1w行),且返回数量不足扫描数量的1/100,这样的操作通常对CPU消耗大高,也比低效,

# mlogfilter mongo.log --scan --shorten 200
2018-05-18T21:57:09.123+0800 I COMMAND [conn683] command cmspace.USER_LOGIN_HISTORY command: find ...e: { acquireCount: { r: 95 } }, Collection: { acquireCount: { r: 95 } } } protocol:op_command 556ms
2018-05-18T21:57:17.381+0800 I COMMAND [conn784] getmore nsspace.StatisticsDay query: { aggre...nt: { r: 10 }, timeAcquiringMicros: { r: 1667 } }, Collection: { acquireCount: { r: 890 } } } 214ms
2018-05-18T22:06:16.148+0800 I COMMAND [conn764] getmore nsspace.StatisticsHour query: { aggr...} }, Database: { acquireCount: { r: 69128 } }, Collection: { acquireCount: { r: 69128 } } } 12053ms
2018-05-18T22:06:24.962+0800 I COMMAND [conn764] getmore nsspace.StatisticsHour query: { aggr... } }, Database: { acquireCount: { r: 69106 } }, Collection: { acquireCount: { r: 69106 } } } 8782ms
2018-05-18T22:06:33.787+0800 I COMMAND [conn764] getmore nsspace.StatisticsHour query: { aggr... } }, Database: { acquireCount: { r: 69111 } }, Collection: { acquireCount: { r: 69111 } } } 8822ms

根据名称空间过滤

# mlogfilter mongo.log --namespace dmspace.DeviceInfo
2018-05-18T21:50:58.105+0800 I COMMAND [conn31] command dmspace.DeviceInfo appName: "MongoDB Shell...adata: { acquireCount: { w: 16 } }, oplog: { acquireCount: { w: 16 } } } protocol:op_command 2963ms
2018-05-18T21:50:59.195+0800 I COMMAND [conn31] command dmspace.DeviceInfo appName: "MongoDB Shell...tadata: { acquireCount: { w: 16 } }, oplog: { acquireCount: { w: 16 } } } protocol:op_command 936ms
2018-05-18T21:51:00.173+0800 I COMMAND [conn44] command dmspace.DeviceInfo command: insert { inser...tadata: { acquireCount: { w: 16 } }, oplog: { acquireCount: { w: 16 } } } protocol:op_command 745ms
2018-05-18T21:51:00.433+0800 I COMMAND [conn44] command dmspace.DeviceInfo command: insert { inser...tadata: { acquireCount: { w: 16 } }, oplog: { acquireCount: { w: 16 } } } protocol:op_command 252ms

依据操作类型过滤

# mlogfilter mongo.log --operation update
2018-05-18T21:56:25.114+0800 I WRITE [conn156] update dmspace.PolicyTask query: { _id: "###" } pla...Count: { w: 2 } }, Metadata: { acquireCount: { w: 1 } }, oplog: { acquireCount: { w: 1 } } } 2630ms
2018-05-18T21:56:25.114+0800 I WRITE [conn92] update nsspace.TimerTask query: { _id: "###" } planS...Count: { w: 2 } }, Metadata: { acquireCount: { w: 1 } }, oplog: { acquireCount: { w: 1 } } } 1264ms
2018-05-18T21:56:25.125+0800 I WRITE [conn43] update dmspace.TaskHistory query: { _id: "###" } pla...Count: { w: 2 } }, Metadata: { acquireCount: { w: 1 } }, oplog: { acquireCount: { w: 1 } } } 2643ms
2018-05-18T21:56:30.027+0800 I WRITE [conn532] update dmspace.TaskHistory query: { _id: "###" } pl...eCount: { w: 2 } }, Metadata: { acquireCount: { w: 1 } }, oplog: { acquireCount: { w: 1 } } } 868ms
2018-05-18T21:56:32.115+0800 I WRITE [conn517] update dmspace.TaskHistory query: { _id: "###" } pl...eCount: { w: 2 } }, Metadata: { acquireCount: { w: 1 } }, oplog: { acquireCount: { w: 1 } } } 497ms

获得有时间点之后1小时之日记

# mlogfilter mongo.log --from Apr 6 0:00 --to "+1h" | tail -n3
2018-05-19T00:59:59.876+0800 I COMMAND [conn16386] command nsspace.StatisticsHour command: find { find: "###", filter: { user: "###", region: "###", appKey: "###", recordTime: { $lte: "###" }, $and: [ { recordTime: { $gte: "###" } } ] }, shardVersion: [ "###", "###" ] } planSummary: ### keysExamined:249767 docsExamined:249767 cursorExhausted:1 numYields:1952 nreturned:84 reslen:29748 locks:{ Global: { acquireCount: { r: 3906 } }, Database: { acquireCount: { r: 1953 } }, Collection: { acquireCount: { r: 1953 } } } protocol:op_command 319ms
2018-05-19T00:59:59.879+0800 I COMMAND [conn15998] command nsspace.StatisticsHour command: find { find: "###", filter: { user: "###", region: "###", appKey: "###", recordTime: { $lte: "###" }, $and: [ { recordTime: { $gte: "###" } } ] }, shardVersion: [ "###", "###" ] } planSummary: ### keysExamined:249767 docsExamined:249767 cursorExhausted:1 numYields:1954 nreturned:84 reslen:29833 locks:{ Global: { acquireCount: { r: 3910 } }, Database: { acquireCount: { r: 1955 } }, Collection: { acquireCount: { r: 1955 } } } protocol:op_command 321ms

mlogfilter提供了非常灵活的日子条件设置,除了可以指定起始、结束时间外,还能由此偏移量划分范围。

时区转换

# mlogfilter mongo.log --tiemzone 2 > mongo-correct.log

以上命令将日期调大2个时区,输出到mongo-correct.log,这当处理国际化系统的状况被十分管用。

又多详情戳这里

program.csusing System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;

class S
    {
       public static void Main()
        {
            pcount = Environment.ProcessorCount;
            Console.WriteLine("Proc count = " + pcount);
            ThreadPool.SetMinThreads(4, -1);
            ThreadPool.SetMaxThreads(4, -1);

            t1 = new Task(A, 1);
            t2 = new Task(A, 2);
            t3 = new Task(A, 3);
            t4 = new Task(A, 4);
            Console.WriteLine("Starting t1 " + t1.Id.ToString());
            t1.Start();
            Console.WriteLine("Starting t2 " + t2.Id.ToString());
            t2.Start();
            Console.WriteLine("Starting t3 " + t3.Id.ToString());
            t3.Start();
            Console.WriteLine("Starting t4 " + t4.Id.ToString());
            t4.Start();

            Console.ReadLine();
        }

        static void A(object o)
        {
            B(o);
        }
        static void B(object o)
        {
            C(o);
        }
        static void C(object o)
        {
            int temp = (int)o;

            Interlocked.Increment(ref aa);
            while (aa < 4)
            {
                ;
            }

            if (temp == 1)
            {
                // BP1 - all tasks in C

                Debugger.Break();
                waitFor1 = false;
            }
            else
            {
                while (waitFor1)
                {
                    ;
                }
            }
            switch (temp)
            {
                case 1:
                    D(o);
                    break;
                case 2:
                    F(o);
                    break;
                case 3:
                case 4:
                    I(o);
                    break;
                default:
                    Debug.Assert(false, "fool");
                    break;
            }
        }
        static void D(object o)
        {
            E(o);
        }
        static void E(object o)
        {
            // break here at the same time as H and K

            while (bb < 2)
            {
                ;
            }
            //BP2 - 1 in E, 2 in H, 3 in J, 4 in K

            Debugger.Break();
            Interlocked.Increment(ref bb);

            //after

            L(o);
        }
        static void F(object o)
        {
            G(o);
        }
        static void G(object o)
        {
            H(o);
        }
        static void H(object o)
        {
            // break here at the same time as E and K

            Interlocked.Increment(ref bb);
            Monitor.Enter(mylock);
            while (bb < 3)
            {
                ;
            }
            Monitor.Exit(mylock);


            //after

            L(o);
        }
        static void I(object o)
        {
            J(o);
        }
        static void J(object o)
        {
            int temp2 = (int)o;

            switch (temp2)
            {
                case 3:
                    t4.Wait();
                    break;
                case 4:
                    K(o);
                    break;
                default:
                    Debug.Assert(false, "fool2");
                    break;
            }
        }
        static void K(object o)
        {
            // break here at the same time as E and H

            Interlocked.Increment(ref bb);
            Monitor.Enter(mylock);
            while (bb < 3)
            {
                ;
            }
            Monitor.Exit(mylock);


            //after

            L(o);
        }
        static void L(object oo)
        {
            int temp3 = (int)oo;

            switch (temp3)
            {
                case 1:
                    M(oo);
                    break;
                case 2:
                    N(oo);
                    break;
                case 4:
                    O(oo);
                    break;
                default:
                    Debug.Assert(false, "fool3");
                    break;
            }
        }
        static void M(object o)
        {
            // breaks here at the same time as N and Q

            Interlocked.Increment(ref cc);
            while (cc < 3)
            {
                ;
            }
            //BP3 - 1 in M, 2 in N, 3 still in J, 4 in O, 5 in Q

            Debugger.Break();
            Interlocked.Increment(ref cc);
            while (true)
                Thread.Sleep(500); // for ever

        }
        static void N(object o)
        {
            // breaks here at the same time as M and Q

            Interlocked.Increment(ref cc);
            while (cc < 4)
            {
                ;
            }
            R(o);
        }
        static void O(object o)
        {
            Task t5 = Task.Factory.StartNew(P, TaskCreationOptions.AttachedToParent);
            t5.Wait();
            R(o);
        }
        static void P()
        {
            Console.WriteLine("t5 runs " + Task.CurrentId.ToString());
            Q();
        }
        static void Q()
        {
            // breaks here at the same time as N and M

            Interlocked.Increment(ref cc);
            while (cc < 4)
            {
                ;
            }
            // task 5 dies here freeing task 4 (its parent)

            Console.WriteLine("t5 dies " + Task.CurrentId.ToString());
            waitFor5 = false;
        }
        static void R(object o)
        {
            if ((int)o == 2)
            {
                //wait for task5 to die

                while (waitFor5) { ;}


                int i;
                //spin up all procs

                for (i = 0; i < pcount - 4; i++)
                {
                    Task t = Task.Factory.StartNew(() => { while (true);});
                    Console.WriteLine("Started task " + t.Id.ToString());
                }

                Task.Factory.StartNew(T, i + 1 + 5, TaskCreationOptions.AttachedToParent); //scheduled

                Task.Factory.StartNew(T, i + 2 + 5, TaskCreationOptions.AttachedToParent); //scheduled

                Task.Factory.StartNew(T, i + 3 + 5, TaskCreationOptions.AttachedToParent); //scheduled

                Task.Factory.StartNew(T, i + 4 + 5, TaskCreationOptions.AttachedToParent); //scheduled

                Task.Factory.StartNew(T, (i + 5 + 5).ToString(), TaskCreationOptions.AttachedToParent); //scheduled


                //BP4 - 1 in M, 2 in R, 3 in J, 4 in R, 5 died

                Debugger.Break();
            }
            else
            {
                Debug.Assert((int)o == 4);
                t3.Wait();
            }
        }
        static void T(object o)
        {
            Console.WriteLine("Scheduled run " + Task.CurrentId.ToString());
        }
        static Task t1, t2, t3, t4;
        static int aa = 0;
        static int bb = 0;
        static int cc = 0;
        static bool waitFor1 = true;
        static bool waitFor5 = true;
        static int pcount;
        static S mylock = new S();
    }

4. 图片呈现

mplotqueries
是根据tkinter实现之图组件,可以以日志被扁平的亲笔信息易为图形式。
输入以下命令:

mplotqueries mongo.log --group operations --output-file operations.png

若得拿走一个遵循操作分组输出的散点图,如下图:
图片 3

左手的Y轴是duration,即操作的执行时长,下边的X轴是日。每个操作以觊觎中都见面起一个描点,因此散点图会在重重层。
自然,你为堪透过聚合名称进行分组输出,如下面的吩咐:

mplotqueries mongo.log --group namespace --group-limit 20 --type scatter --yaxis nscanned --output-file namespace_nscan.png

输出的图形将随名空间进行分组(限显示20只),y轴为nscanned值,即扫描记录数据
图片 4

默认情况下,y轴的呈现为时长(during),可指定为另外指标:

指标名称 说明
nscanned 扫描数
nupdated 更新数
ninserted 插入数
ntoreturn 返回数
numYields 让步次数
r 读锁
w 写锁

奇迹你并无干具体的某部操作,而是要看某个时刻段,某类操作还是某集合的操作占比。
按各级时,每个集合的操作比例分布,此时得以直方图

mplotqueries mongo.log --group namespace --bucketsize 3600 --group-limit 10 --type histogram --output-file namespaces_perhour.png

图片 5

在眼前早已提过,连接数之监测工作大关键,mplotqueries也提供了连日变更统计类型

mplotqueries mongo.log --type connchurn --bucketsize 3600 --output-file connchurn_perhour.png

图片 6

在大多数状下,低效的操作往往来自大量的scan扫描,尤其当return数远低于scan时会见愈来愈低效。
足由此点名 nscanned/n 参数输出该维度的图,即扫描数/返回数

mplotqueries mongo.log --type nscanned/n --group-limit 20 --output-file nscan.png

图片 7

出口事件不断图
勤以跟踪某平等接近耗时操作还是事件频仍用运用,比如oplog的齐、创建索引等,我们要观看事件之推行上。
还要还亟需伴随有操作统计,用于配合举行资源监察分析。具体一点哪怕是,你尽了一个耗时操作,在某些情况下本着工作访问可能
产生了影响,如工作访问过并伴随DB服务器资源的报警,如CPU飙高,在继承之辨析着要经过耗时操作、以及以段工作访问的分布进行归纳分析。

以下的命展示了一个一流用法

# 创建一个overlay
grep "index" mongo.log | mplotqueries --type durline --overlay
# 叠加overlay输出图表
mplotqueries mongo.log --group operation --output-file duration.png

图片 8

By the way,如果未欲生成那么多的图,mtools还提供了一个偷懒的家伙
mlogvis。可以直接生成html页面,内置强大的本子
基本上覆盖了mplotqueries的大部图功能。

# mlogvis mongo.log

图片 9

查看更多为此法

盼你已经开喜欢mtools,并都尝试。下面提供了简约的装方式

 

如何设置

由于篇幅所限,这里就提供Centos下之装置方式

  • 预备Python的条件(2.7要么3.5),目前多数批发本的linux都富含了python。
    要是无Python,执行yum install python python-devel 完成安装
    保险pip已经设置,执行pip进行检测,如果无装可参看官方证实进行安装。

  • 安装python-tk
    执行命令如下:

yum install python-tools

外linux系统(如ubuntu/opensuse)则要安装python-tk软件包

  • 装依赖模块

pip install psutil
pip install pymongo
pip install matplotlib
pip install numpy

说明
每个模块的来意可参考下表:

模块名称 作用
psutil 用于管理进程的工具
pymongo mongodb python驱动
matplotlib python的2D图表渲染模块
numpy 支持科学计算的工具
  • 安装mtools

pip install mtools

至此,你应当得到了一个一度装好之mtools环境,如果愿意安装新型的非稳定版本,可以由此源码安装

以F5,开始运行:

参照文档

Mongodb干货系列-定期巡检的Mtools
关于mtools的介绍
mtools安装指导

由于Debugger.Break();

所以当行及此处的早晚,Debugger会中断。

 

这时节又看调试窗口会意识差不多了几乎单窗口:

图片 10

 

点击调试->窗口->并行任务,界面如下:

图片 11

依照下F5,继续运行:

图片 12 

双击查看相应等待的天职,就足以理解此工作线程为什么等待了。

 

例如:

图片 13

累按F5,运行,你应有会看到:

图片 14

总之关于当前运行的并行任务你还可以看之至。

 

 

关闭程序,重新F5,进入调试模式

 

选择调试**->窗口->并行堆栈**

足见见:

图片 15

其中蓝线代表时正值执行之线程。

倘右键点击方法视图的S.C
,可以观看右键菜单如下:图片 16

点击切换方式视图

图片 17

足见到:

图片 18

 

关闭程序,重新F5,进入调试模式

 

点击调试**->窗口->线程:**

得看到:

图片 19

脚下控制台的享有线程都于此。

以线程上点击右键可以冻结线程:

图片 20

 

冷冻线程也就是是Pause线程,

冻结的线程可以让开,也不怕是Resume。

 

其它的窗口:

调试->窗口->模块:可以观看眼前程序加载的装有模块。

图片 21

调试->窗口->进程:

图片 22

调试->窗口->反汇编:

图片 23

调试->窗口->寄存器:

图片 24

调节->窗口->调用堆栈:

调用堆栈窗口是于常用之窗口:

图片 25

高达图表示先调用A方法,接着B方法,接着C方法。

呢得以看是C方法是B调用,而B方法是A调用的。

另外窗口于常用,就未介绍了,是无是来部分你没因此到之窗口也?

留下评论

网站地图xml地图