最小化文件之间的 compilation dependencies(编译依赖)

卫衣 / 双肩包 / T 恤/羽绒服等任选,下单送 CSDN 年卡 程序员周边任选一款实物,直接赠送 CSDN 会员年卡+ Coding Plan,写代码学习装备一起拿下 立即抢购
我们进入到某个C++ 程序中,对一个 class 的 implementation(实现)进行了细微的改变。不是 class 的 interface(接口),只是 implementation(实现),仅仅是 private 的东西。然后 rebuild(重建)这个程序,预计这个任务应该只花费几秒钟。毕竟只有一个 class 被改变。点了一下 Build 或者键入 make(或者其它类似的事情),然后惊呆了,继而被郁闷,就像突然意识到整个世界都被重新编译和连接!
问题在于 C++ 没有做好从 implementations(实现)中剥离 interfaces(接口)的工作。一个 class definition(类定义)不仅指定了一个 class interface(类接口)而且有相当数量的 implementation details(实现细节)。例如:
class Person {
public:
  Person(const std::string& name, const Date& birthday,
         const Address& addr);
  std::string name() const;
  std::string birthDate() const;
  std::string address() const;
private:
      std::string theName;        // implementation detail
      Date theBirthDate;          // implementation detail
      Address theAddress;         // implementation detail
};
这里,如果不访问 Person 的 implementations(实现)使用到的 class,也就是 stringDateAddress 的定义,class Person 就无法编译。这样的定义一般通过 #include 指令提供,所以在定义 Person class 的文件中,很可能会找到类似这样的东西:
#include <string>
#include "date.h"
#include "address.h"
不幸的是,这样就建立了定义 Person 的文件和这些头文件之间的 compilation dependency(编译依赖)。如果这些头文件中的任何一个发生了变化,或者如果这些头文件所依赖的任何一个文件发生了变化,包含 Person class 的文件和使用了 Person 的任何文件一样必须重新编译,这样的 cascading compilation dependencies(层叠编译依赖)导致了数不清的麻烦。
C++ 为什么坚持要将一个 class 的implementation details(实现细节)放在 class definition(类定义)中。例如,为什么不能这样定义 Person,单独指定这个 class 的 implementation details(实现细节)呢?
namespace std {
     class string;             // forward declaration (an incorrect
}                              // one — see below)
class Date;                    // forward declaration
class Address;                 // forward declaration
class Person {
public:
      Person(const std::string& name, const Date& birthday,
                 const Address& addr);
      std::string name() const;
      std::string birthDate() const;
      std::string address() const;
    ...
};
如果这样可行,只有在 class 的 interface 发生变化时,Person 的客户才有必要重新编译。
这个想法有两个问题。第一个,string 不是一个 class,它是一个 typedef (for basic_string<char>)。造成的结果就是,string 的 forward declaration(前向声明)是不正确的。正确的 forward declaration(前向声明)要复杂得多,因为它包括其它的模板。然而,这还不是要紧的,因为不应该试图手动声明标准库的部件。替代做法是,直接使用适当的 #includes 并让它去做。标准头文件不太可能成为编译的瓶颈,特别是在你的构建环境允许你利用 precompiled headers(预编译头文件)时。如果解析标准头文件真的成为一个问题。你也许需要改变你的 interface 设计,避免使用导致不受欢迎的 #includes 的标准库部件。
第二个(而且更重要的)难点是 forward-declaring(前向声明)的每一件东西必须让编译器在编译期间知道它的 objects 的大小。考虑:
int main()
{
 int x;                // define an int
 Person p( params );   // define a Person
}
当编译器看到 x 的定义,它们知道它们必须分配足够的空间(一般是在栈上)用于保存一个 int。这没什么问题,每一个编译器都知道一个 int 有多大。当编译器看到 p 的定义,它们知道它们必须分配足够的空间给一个 Person,但是它们怎么推测出一个 Person object 有多大呢?它们得到这个信息的唯一方法是参考这个 class 的定义,但是如果一个省略了实现细节的 class definition(类定义)是合法的,编译器怎么知道该分配多少空间呢?
这个问题在诸如 Smalltalk 和 Java 这样的语言中就不会发生,因为,在这些语言中,定义一个 object 时,编译器仅需要分配足够的空间给一个指向一个 object 的 pointer。也就是说,它们处理上面的代码就像这些代码是这样写的:
int main()
{
  int x;               // define an int
  Person *p;           // define a pointer to a Person
  ...
}
这当然是合法的 C++,所以也可以自己来玩这种“将 object 的实现隐藏在一个指针后面”的游戏。对 Person 做这件事的一种方法就是将它分开到两个 classes 中,其中一个仅提供一个 interface,另一个实现这个 interface。如果那个 implementation class(实现类)名为 PersonImplPerson 就可以如此定义:
#include <string>                      // standard library components
                                       // shouldn't be forward-declared
#include <memory>                      // for tr1::shared_ptr; see below
class PersonImpl;                      // forward decl of Person impl. class
class Date;                            // forward decls of classes used in
class Address;                         // Person interface
class Person {
public:
 Person(const std::string& name, const Date& birthday,
        const Address& addr);
 std::string name() const;
 std::string birthDate() const;
 std::string address() const;
 ...
private:                                   // ptr to implementation;
  std::tr1::shared_ptr<PersonImpl> pImpl;  // see
Item 13 for info on
};                                         // std::tr1::shared_ptr
这里,main class (Person) 除了一个指向它的 implementation class(实现类) (PersonImpl) 的指针(这里是一个 tr1::shared_ptr)之外不包含任何 data member。这样一个设计通常被说成是使用了 pimpl idiom ("pointer to implementation")(“指向实现的指针”)。在这样的 classes 中,那个指针的名字经常是 pImpl,就像上面那个。
用这样的设计,使 Person 的客户脱离 dates,addresses 和 persons 的细节。这些 classes 的实现可以随心所欲地改变,但 Person 的客户却不必重新编译。另外,因为他们看不到 Person 的实现细节,客户就不太可能写出以某种方式依赖那些细节的代码。这就是 interface(接口)和 implementation(实现)的真正分离。
这个分离的关键就是用对 declarations(声明)的依赖替代对 definitions(定义)的依赖。这就是 minimizing compilation dependencies(最小化编译依赖)的精髓:只要能实现,就让头文件独立自足,如果不能,就依赖其它文件中的声明,而不是定义。其它每一件事都从这个简单的设计策略产生。因此:
当 object references(引用)和 pointers(指针)可以做到时就避免使用 objects。仅需一个类型的声明,就可以定义到这个类型的 references 和 pointers。而定义一个类型的 objects 必须要存在这个类型的定义。
只要能做到,就用对 class declarations(类声明)的依赖替代对 class definitions(类定义)的依赖。注意在声明一个使用一个 class 的函数时绝对不需要有这个 class definition,即使这个函数通过传值方式传递或返回这个 class:
class Date;                        // class declaration
Date today();                      // fine — no definition
void clearAppointments(Date d);    // of Date is needed
当然,pass-by-value(传值)通常不是一个好主意,但是如果发现自己因为某种原因而使用它,依然不能为引入不必要的 compilation dependencies(编译依赖)辩解。
不定义 Date 就可以声明 todayclearAppointments 的能力可能会令你感到惊奇,但是它其实并不像看上去那么不同寻常。只有有人调用了这些函数,Date 的定义才必须在调用之前被看到。为什么费心去声明没有人调用的函数,觉得奇怪吗?很简单。并不是没有人调用它们,而是并非每个人都要调用它们。如果有一个包含很多 function declarations(函数声明)的库,每一个客户都要调用每一个函数是不太可能的。通过将提供 class definitions(类定义)的责任从你的 function declarations(函数声明)的头文件转移到客户的包含 function calls(函数调用)的文件,就消除了客户对他们并不真正需要的 type definitions(类型定义)的人为依赖。
为 declarations(声明)和 definitions(定义)分别提供头文件。为了便于坚持上面的指导方针,头文件需要成对出现:一个用于 declarations(声明),另一个用于 definitions(定义)。当然,这些文件必须保持一致。如果一个 declaration(声明)在一个地方被改变了,它必须在两处都被改变。得出的结果是:库的客户应该总是 #include 一个 declaration(声明)文件,而不是自己 forward-declaring(前向声明)某些东西,而库的作者应该提供两个头文件。例如,想要声明 todayclearAppointmentsDate 的客户不应该像前面展示的那样手动前向声明 Date。更合适的是,它应该 #include 适当的用于 declarations(声明)的头文件:
#include "datefwd.h"             // header file declaring (but not
                                // defining) class Date
Date today();                   // as before
void clearAppointments(Date d);
declaration-only(仅有声明)的头文件的名字 "datefwd.h" 基于来自标准 C++ 库的头文件 <iosfwd><iosfwd> 包含 iostream 组件的 declarations(声明),而它们相应的 definitions(定义)在几个不同的头文件中,包括 <sstream><streambuf><fstream><iostream>
<iosfwd> 在其它方面也有启发意义,而且它表明本 Item 的建议对于 templates(模板)和 non-templates(非模板)一样有效。尽管在很多构建环境中,template definitions(模板定义)的典型特征是位于头文件中,但有些环境允许 template definitions(模板定义)位于非头文件中,所以为模板提供一个 declaration-only(仅有声明)的头文件依然是有意义的。<iosfwd> 就是一个这样的头文件。
C++ 还提供了 export 关键字允许将 template declarations(模板声明)从 template definitions(模板定义)中分离出来。不幸的是,支持 export 的编译器非常少见,而与 export 打交道的实际经验就更少了。结果是,现在就说 export 在高效 C++ 编程中扮演什么角色还为时尚早。
Person 这样的使用 pimpl idiom(惯用法)的 classes 经常被称为 Handle classes。为了避免对这样的 classes 实际上做什么事的好奇心,一种方法是将所有对它们的函数调用都转送给相应的 implementation classes(实现类),而让那些 classes 来做真正的工作。例如,这是两个 Person 的 member functions(成员函数)被实现的例子:
#include "Person.h"          // we're implementing the Person class,
                             // so we must #include its class definition
#include "PersonImpl.h"      // we must also #include PersonImpl's class
                             // definition, otherwise we couldn't call
                             // its member functions; note that
                             // PersonImpl has exactly the same
                             // member functions as Person — their
                             // interfaces are identical
Person::Person(const std::string& name, const Date& birthday,
               const Address& addr)
: pImpl(new PersonImpl(name, birthday, addr))
{}
std::string Person::name() const
{
  return pImpl->name();
}
注意 Person 的 constructor(构造函数)是如何调用 PersonImpl 的 constructor(构造函数)的(通过使用 new ),以及 Person::name 是如何调用 PersonImpl::name 的。这很重要。使 Person 成为一个 Handle class 不需要改变 Person 要做的事情,仅仅是改变了它做事的方法。
另一个不同于 Handle class 的候选方法是使 Person 成为一个被叫做 Interface class 的特殊种类的 abstract base class(抽象基类)。这样一个 class 的作用是为 derived classes(派生类)指定一个 interface(接口)。结果,它的典型特征是没有 data members(数据成员),没有 constructors(构造函数),有一个 virtual destructor(虚拟析构函数)和一组指定 interface(接口)的 pure virtual functions(纯虚拟函数)。
Interface classes 类似 Java 和 .NET 中的 Interfaces,但是 C++ 并不会为 Interface classes 强加那些 Java 和 .NET 为 Interfaces 强加的种种限制。例如,Java 和 .NET 都不允许 Interfaces 中有 data members(数据成员)和 function implementations(函数实现),但是 C++ 不禁止这些事情。C++ 的较大弹性是有用处的。在一个 hierarchy(继承体系)的所有 classes 中 non-virtual functions(非虚拟函数)的实现应该相同,因此将这样的函数实现为声明它们的 Interface class 的构件就是有意义的。
一个 Person 的 Interface class 可能就像这样:
class Person {
public:
  virtual ~Person();
  virtual std::string name() const = 0;
  virtual std::string birthDate() const = 0;
  virtual std::string address() const = 0;
  ...
};
这个 class 的客户必须针对 Person 的指针和引用进行编程,因为实例化包含 pure virtual functions(纯虚拟函数)的 classes 是不可能的。(然而,实例化从 Person 派生的 classes 是可能的)和 Handle classes 的客户一样,除非 Interface class 的 interface(接口)发生变化,否则 Interface classes 的客户不需要重新编译。
一个 Interface class 的客户必须有办法创建新的 objects。他们一般通过调用一个为“可以真正实例化的 derived classes(派生类)”扮演 constructor(构造函数)角色的函数做到这一点的。这样的函数一般称为 factory functions或 virtual constructors(虚拟构造函数)。他们返回指向动态分配的支持 Interface class 的 interface 的 objects 的指针(smart pointers(智能指针)更合适)。这样的函数在 Interface class 内部一般声明为 static
class Person {
public:
 static std::tr1::shared_ptr<Person>    // return a tr1::shared_ptr to a new
   create(const std::string& name,      // Person initialized with the
          const Date& birthday,         // given params; see
Item 18 for
          const Address& addr);         // why a tr1::shared_ptr is returned
};
客户就像这样使用它们:
std::string name;
Date dateOfBirth;
Address address;
// create an object supporting the Person interface
std::tr1::shared_ptr<Person> pp(Person::create(name, dateOfBirth, address));
std::cout << pp->name()                 // use the object via the
          << " was born on "            // Person interface
          << pp->birthDate()
          << " and now lives at "
          << pp->address();
// the object is automatically deleted when pp goes out of scope
当然,在某些场合,必须定义支持 Interface class 的 interface(接口)的 concrete classes (具体类)并调用真正的 constructors(构造函数)。这所有的一切都发生在幕后,隐藏在那个包含了 virtual constructors(虚拟构造函数)的实现的文件之内。例如,Interface class Person 可以有一个 concrete derived class(具体派生类)RealPerson,它为继承到的 virtual functions(虚拟函数)提供了实现:
class RealPerson: public Person {
public:
  RealPerson(const std::string& name, const Date& birthday,
             const Address& addr)
  : theName(name), theBirthDate(birthday), theAddress(addr)
  {}
  virtual ~RealPerson() {}
  std::string name() const;        // implementations of these
  std::string birthDate() const;   // functions are not shown, but
  std::string address() const;     // they are easy to imagine
private:
  std::string theName;
  Date theBirthDate;
  Address theAddress;
};
给出了 RealPerson,写 Person::create 就微不足道了:
std::tr1::shared_ptr<Person> Person::create(const std::string& name,
                                            const Date& birthday,
                                            const Address& addr)
{
 return std::tr1::shared_ptr<Person>(new RealPerson(name, birthday,addr));
}
Person::create 的一个更现实的实现会依赖于诸如,另外的函数参数的值,从文件或数据库读出的数据,环境变量等等,创建不同 derived class(派生类)类型的 objects。
RealPerson 示范了实现一个 Interface class 的两种最通用的机制中的一种:从 Interface class(Person)继承它的 interface specification(接口规格),然后实现 interface(接口)中的函数。实现一个 Interface class 的第二种方法包含 multiple inheritance(多继承)。
Handle classes 和 Interface classes 从 implementations(实现)中分离出 interfaces(接口),因此减少了文件之间的编译依赖。
在Handle classes 的情况下,member functions 必须通过 implementation pointer(实现的指针)得到 object 的数据。这就在每次访问中增加了一个间接层。而且必须在存储每一个 object 所需的内存量中增加这一 implementation pointer(实现的指针)的大小。最后,这一 implementation pointer(实现的指针)必须被初始化(在 Handle class 的 constructors(构造函数)中)为指向一个动态分配的 implementation object(实现的对象),所以你要承受动态内存分配(以及随后的释放)所固有的成本和遭遇 bad_alloc (out-of-memory) exceptions(异常)的可能性。
对于 Interface classes,每一个函数调用都是虚拟的,所以每调用一次函数就要支付一个间接跳转的成本。还有,从 Interface class 派生的 objects 必须包含一个 virtual table pointer。这个 pointer 可能增加存储一个 object 所需的内存量,这依赖于这个 Interface class 是否是这个 object 的 virtual functions(虚拟函数)的唯一来源。
最后,无论 Handle classes 还是 Interface classes 都不能大量使用 inline functions(内联函数)。一般情况下函数本体必须在头文件中才能做到 inline,但是 Handle classes 和 Interface classes 一般都被设计用于隐藏类似函数本体这样的实现细节。
然而,仅仅因为它们所涉及到的成本而放弃 Handle classes 和 Interface classes 会成为一个严重的错误。virtual functions(虚拟函数)也是一样,但还是不能放弃它们。替代做法是,考虑以一种改进的方式使用这些技术。在开发过程中,使用 Handle classes 和 Interface classes 来最小化当实现发生变化时对客户的影响。当能看出在速度和/或大小上的不同足以证明增加 classes 之间的耦合是值得的时候,可以用 concrete classes(具体类)取代 Handle classes 和 Interface classes 供产品使用。
 
Things to Remember
最小化编译依赖后面的一般想法是用对 declarations(声明)的依赖取代对 definitions(定义)的依赖。基于此想法的两个方法是 Handle classes 和 Interface classes。
库头文件应该以完整并且 declaration-only(只有声明)的形式存在。无论是否包含 templates(模板)都适用于这一点。
 
  
MySQL5.7无法连接到[本地] MySQL 服务器 如果您的服务器正在侦听不同的端口,请更改该值。通常意味着系统上没有运行 MySQL 服务器,或者您在尝试连接服务器时使用了不正确的 Unix 套接字文件名或 TCP/IP 端口号。您应该检查是否有一台 MySQL 服务器正在运行、是否已启用网络连接、以及您指定的网络端口是否是服务器上配置的端口。系统变量的情况下启动,并且在运行服务器的主机上运行客户端,则还可以使用命名管道进行连接。LAN 连接是安全的,因为数据包到达时延迟很长的可能性很小,而通过距离和延迟相对较长的互联网则可能如此。 阅读详情

相关推荐

【问题解决记录】Windows 系统小皮面板(phpStudy Pro)MySQL8 无法启动及多 MySQL 共存问题解决

摘要:本文介绍了Windows系统中phpStudy Pro面板MySQL8无法启动的问题及解决方案。当MySQL8启动失败时,首先检查端口冲突,发现3306端口被占用。进一步排查发现系统已存在另一个MySQL服务。通过删除原MySQL服务并重新注册为不同名称(MYSQL8),同时修改phpStudy的MySQL端口为3307,成功实现了两个MySQL实例的共存。关键步骤包括:停止并删除原服务、修改端口、重新注册新服务启动。该方法适用于需要保留原有MySQL服务的同时运行phpStudy MySQL的情况

一名资深全栈开发工程师的博客 1955

MySQL连接工具无法连接的问题及解决方法

本文介绍了MySQL连接工具无法连接的一些常见问题及相应的解决方法。在尝试解决连接问题之前,请确保MySQL服务器正在运行,并检查连接配置、防火墙设置和用户权限。MySQL是一个流行的关系型数据库管理系统,可以通过各种工具进行连接和管理。本文将探讨一些可能导致连接问题的原因,并提供相应的解决方法。防火墙设置可能会阻止MySQL连接。确保您使用的用户名和密码具有足够的权限来连接MySQL数据库。确保您使用的连接工具中的MySQL连接配置正确无误。如果您使用的是其他防火墙工具,请根据其文档进行相应的配置。

MwgmPhilosophy的博客 791

MySQL安装运行时出现服务器无法响应控制的解决办法

MySQL安装运行时出现服务器无法响应控制的解决办法 文章目录MySQL安装运行时出现服务器无法响应控制的解决办法前言一、安装的环境说明二、出现服务器无法响应控制的几个原因1.缺失运行库2.mysql.ini配置文件问题2.1配置文件没有用ANSI编码保存,而是用UTF-8编码保存2.2配置文件中basedir与datadir中的文件路径的‘/’改为‘//’3.其他原因及其解决方法3.1在cmd窗口启动MySQL没有用管理员身份启动,权限不够。3.2其他方法4.如果以上方法都不能解决问题小结 前言 最

weixin_46704975的博客 1633

一个程序运行 一段时间连接不上数据库了(数据库运行正常),重起系统所在的服务器就好了

系统运行中奇怪的问题

qq_36247791的博客 709

windows服务器下,mysql运行一段时间之后忽然无法连接,但是mysql服务启动正常...

出现这种情况以前都是重启服务器可以解决,但是治标不治本,一段时间之后仍然会出现此问题。 此问题不是mysql应用程序的问题而是windows server system 的配置问题。因此需要修改windows server system的配置。 具体办法为修改windows 注册表: 有两个相关值,一是修改MaxUserPort(最大连接数);另一个是修改TcpTimedWaitD...

dbva7063的博客 1202

开启mysql服务器电脑死机_mysql 服务器重启后,很快又死机了,请高手看下 错误日志...

请高手看下 错误日志localhost.localdomain.err 文件的内容Number of processes running now: 0131004 02:43:19 mysqld restartedInnoDB: The log sequence number in ibdata files does not matchInnoDB: the log sequence number...

weixin_42577243的博客 282

nacos连接mysql失败_mysql服务启动连接不上的解决方法

mysql服务启动,但是连接不上,如何解决?登陆报错:root@localhost:~# mysql -u root -pEnter password:ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)root@localhost:~# serv...

weixin_34434736的博客 2466

MySQL启动不了,无法启动MySQL服务解决技巧

如果是因为非法关机等原因导致MYSQL无法启动启动有问题的,最好使用重新安装的或确认是OK的MYSQL数据表及ibdata1、mysql.pid、ib_logfile0等文件进行覆盖,天缘试过遇到过多次这种情况,就是原来的MYSQL表有问题了,总是无法启动,但是更换成新表就可以。如果是重新安装的MYSQL,请确认安装后的MYSQL经过第一次配置,否则会缺少my.ini文件,配置方法,可以在安装到最后一步时选择,现在开始配置MYSQL,或在程序组中运行MYSQL配置向导。本文先列一下常见的解决方法。

目标检测专栏持续更新中,改进YOLO系列通用,适用v5、v7、v8、所有博客均是团队原创博客,所有文章禁止转载,违者必究。 1万+

Mysql服务无法启动MySQL安装

在打开控制面板》》管理工具》》服务》》m8(本人设置MySQL服务名为m8)时,出现“本地计算机上的mysql服务启动后停止,某些服务在未由其他服务或程序使用时将自动停止。”或者在控制台net start MySQL时,出现MySQL服务无法启动服务没有报告任何错误。cd E:\mysql\mysql-8.0.31-winx64\bin (这是本人安装的路径,要以自己的安装位置为准)本地计算机上的mysql服务启动后停止,某些服务在未由其他服务或程序使用时将自动停止。输入 show databases;

2302_76521190的博客 5020

连接MySQL 出现 2003 无法连接MySQL服务器 (10061 “未知错误“)

本地连接MySQL 出现 2003 无法连接MySQL服务器 (10061 “未知错误”)

weixin_62827213的博客 2603

mysql‘ 不是内部或外部命令、Can‘t connect to MySQL server、mysql服务无法启动、Access denied for user ‘root‘等解决办法

此文章梳理windows系统连接mysql 8.0数据库过程中遇到的问题,mysql8.0与版本5的操作略有不同,请知悉~ 问题一:‘mysql’ 不是内部或外部命令,也不是可运行的程序 问题二:ERROR 2003 (HY000): Can’t connect to MySQL server on ‘localhost:3306’ (10061) 问题三:mysql 服务正在启动 .mysql 服务无法启动服务没有报告任何错误。 问题四:ERROR 1045 (28000): Access denied

weixin_42827025的博客 1万+

如何在Windows上设置启动MySQL服务

当在Windows安装Mysql后,有时候有可能会出现重启电脑Mysql服没有自动启动,那么就需要手动的进行启动!那么下面就介绍一下如何在Windows上设置启动MySQL服务以上就是关于在Windows启动MySQL服务的详细指南。希望对您有所帮助!

咖啡程序员 5986

本地电脑WIN10连接阿里云WINDOWS服务器上搭建的MySQL数据库

前言 连接阿里云WINDOWS服务器上搭建的MySQL数据库,必须要做以下准备工作。 1、阿里云网站注册购买阿里云WINDOWS服务器 https://www.aliyun.com/?utm_content=se_1000301881 警告:购买的阿里云WINDOWS服务器至少需要2G内存,否则MySQL数据库系统无法启动运行。 2、获取公网IP地址并且创建了一个实例,实例已经运行 ...

ba_wang_mao的专栏 2835

Mysql服务启动连接

一、查看并启动MySQL服务。 在Windows XP下安装完MySQL后,它就已经自动启动服务了,并且在开始菜单中有其客户端的快捷方式连接,见图4.1。   图4.1   可以通过Windows服务管理器查看。“开始”-“运行”,输入“services.msc”,回车。弹出Windows服务管理器,然后就可以看见服务名为“mysql”的服务项了,其右边标明“已启动”,见图4.2。   图4.

从无到有 3598

启动连接、断开和停止MySQL服务器

1、启动、停止MySQL服务器 1)、通过系统服务器启动、停止MySQL服务器 如果MySQL设置为windows服务,则可以通过选择“开始”->“控制面板”->“系统和安全”->"管理工具"->“系统和安全”->"管理工具“->"服务”命令打开windows服务器管理器。 2)、在命令提示符下启动和停止MySQL服务器 启...

qq_42080635的博客 1715

mysql显示无法启动服务器,MySql服务器无法启动

对不起,我试图设置MySQL在我的机器上工作完全没有我的元素。我正在运行Windows 7 32x,并没有使用WAMP或任何其他类型的服务器设置。我没有任何问题下载并安装了MySQL网站上的所有内容,并且在安装期间,我选择了一个启动服务器的选项。但是,当我尝试与之交互时,服务器从未运行。如果我进入MySQL Workbench中的服务器启动/关闭屏幕并按下“启动服务器”按钮,服务器将在启动运行几...

weixin_29191669的博客 465

重新启动mysql服务器

-重新启动mysql服务器 如何重启MySQL,正确启动MySQL linux平台及windows平台mysql重启方法   Linux下重启MySQL的正确方法:   1、通过rpm包安装的MySQL   service mysqld restart   2、从源码包安装的MySQL   // linux关闭MySQL的命令   $mysql_dir/bin/mysqladmin -uroot -p shutdown   // linux启动MySQL的命令   $mysql_dir/bi

weixin_45084910的博客 9651

解决Spring Boot 部署到服务器无法连接MySQL 问题

今天spring boot 项目终于写好了,打算部署在刚买的digital ocean服务器上,从github pull之后,执行: mvn clean compile package 报错提示: com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure The last pack...

bigbroase的博客 5011

windows启动mysql服务的命令行启动和手动启动方法

今天遇到mysql服务无法启动,上网一查很多人也遇到mysql服务器启动不了的问题,所以就索性整理了windows启动mysql服务的命令行启动和手动启动方法的文章,以便各位遇到同类问题的朋友进行参考。     1、图形界面下启动mysql服务。      在图形界面下启动mysql服务的步骤如下:     (1)打开控制面板->管理工具->服务,如下图所示:     可以看到Mys

Android教程_Android开发教程 16万+
上一篇: 争取 exception-safe code(异常安全代码)
下一篇: 考虑可选的 virtual functions(虚拟函数)的替代方法
armman
博客等级 码龄21年 81粉丝 259原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值