qinghuan
← Java Web / 全部笔记

单元 09 / Java Web

P0 · 必会主线L0 · 零基础

从零准备 MySQL:安装、连接与第一条查询

先启动数据库服务,再用客户端连接、选择独立练习库并执行第一条查询,逐步确认连接和权限。

本篇目录 · 按需要跳转

读完这篇,你能做什么

能在独立练习库创建表、插入并查询一行,重新连接后说明当前数据库和实际连接端口。

学习理由、准备要求与知识点

为什么学它

后续 SQL、MyBatis 和项目排错都依赖一个能够明确连接、独立练习的数据库环境。先验证每一层,才能避免把安装、服务和应用错误混在一起。

先读这些内容

知识点清单

  • 服务端与客户端的职责
  • MSI 安装与 Configurator 配置
  • Windows 服务、安装路径和端口
  • 交互密码输入与连接错误分类
  • SQL 分号与客户端提示符
  • CREATE DATABASE 与 USE
  • 库表层次与首条查询
  • 管理账号与后续应用账号的边界

运行前先确认环境沿用 Windows、MySQL Community Server 8.4;Java 源码定位到 OpenJDK 17u 的 jdk-17.0.16+8 标签。源码模型与算法均使用 Java 17,仅解析配置和模拟驱动选择,不安装软件、不连接数据库。JDK 的 JDBC 管理层不是 MySQL 存储引擎。

01先弄懂它是什么

第一次使用 MySQL,先弄清谁发命令、谁存数据。MySQL Server 是接收连接并执行 SQL 的服务,mysql.exe 或图形工具只是客户端。客户端按主机和端口连接服务,用账号验证身份,选库后再发送语句。安装了图形界面,不代表数据库服务已启动,也不代表账号有权访问目标库。

本篇在 Windows 上使用独立的 qh_sql_lab_01 练习库。按 MySQL 8.4 官方 Windows 安装说明核对架构和运行库,用配套 Configurator 配置服务器及本机管理凭据,并记下实际服务名和端口。已有可用实例可以复用,但应创建用途明确的练习库;不要重新初始化已有数据目录。本机练习无需先向公网开放数据库端口。

在 PowerShell 中启动 mysql.exe,并把主机、端口、账户分别作为参数,使用单独的 -p 让客户端交互读取密码。看到 mysql> 后才输入 SQL。依次查询 SELECT VERSION()、创建练习库、USE 选库、查询 SELECT DATABASE(),再创建 first_note 并插入 hello。

这些检查逐层缩小未知范围:连接成功与语句成功分开,服务端版本与本机客户端版本分开,当前库与连接默认库分开。

文中这几个词,先认一认

服务端
负责接收连接、执行 SQL 和保存数据的进程;关闭查询窗口不会自动停止它。
端点
连接数据库的地址信息,至少包含主机和端口;同一电脑可用不同端口运行多个实例。
schema / 数据库
本篇 MySQL 中用于组织表的一层名字,创建练习库不是另外启动一个数据库服务。
JDBC 驱动
让 Java 的 JDBC 调用能与 MySQL 等具体数据库通信的实现,不是数据库服务本身。

还有陌生词?到术语小抄里看一个具体例子 ↗

02看看它怎么工作

把一次连接拆成阶段后,错误就不再是一团笼统的连接失败。主机或端口错误、服务未监听,通常发生在到达认证之前;Access denied 说明已经进入与身份和来源有关的检查,但还要结合具体错误核实密码、账户来源和权限。成功登录后出现未知数据库,则应检查库名与选择步骤,而不是继续重装驱动。错误文本是定位线索,不应单凭一句消息断言整个网络环境正常。

下图强调检查是累积的。先确认对应服务在运行,再从指定入口连接,认证成功后读取服务端信息和当前库。创建表与插入测试数据只允许落在刚确认的练习命名空间中。每一步都要保留一个小证据,例如版本字符串、当前库名或一行查询结果;这些证据不能互相替代,也不能把安装结束截图当成端到端查询验证。

Java 应用稍后使用 JDBC 时,会增加运行时与驱动两个环节。命令行查询成功不能证明应用的依赖包、连接 URL、密码来源和权限都正确。反过来,Java 报没有合适驱动也不表示 MySQL 进程坏了。因此初学阶段采用逐层检查,比同时改端口、驱动版本和账号更容易找到因果;一次只改一个已被证据指向的因素。

先跑通一个最小例子

在已经安装并启动的 MySQL 8.4 上使用专门的空练习库。先从终端连接,密码在交互提示中输入;进入 mysql 提示符后再执行 SQL。若同名练习库已存在,先检查其用途,不覆盖或删除已有内容。

连接本机 MySQL · PowerShell
mysql --host=127.0.0.1 --port=3306 --user=root --password
在 mysql 提示符中逐句执行 · SQL
SELECT VERSION(), CURRENT_USER(), DATABASE();
CREATE DATABASE qinghuan_learning_lab CHARACTER SET utf8mb4;
USE qinghuan_learning_lab;

CREATE TABLE study_note (
    id BIGINT PRIMARY KEY,
    title VARCHAR(100) NOT NULL
);
INSERT INTO study_note (id, title) VALUES (1, 'Java 集合');
SELECT id, title FROM study_note ORDER BY id;
SHOW CREATE TABLE study_note;

核对运行结果第一条查询的 DATABASE() 在未选择库时可为 NULL。选择库并插入后,查询得到 id=1、title=Java 集合。再次使用相同主键插入应出现主键冲突;这是约束在保护唯一性,不应通过删除表来掩盖问题。root 仅用于本机建库练习,业务程序应使用按需授权的账户。

正在加载流程图…

这条链路验证本次客户端访问,不承诺所有 Java 应用、远程网络或生产负载都已可用。
查看流程图源码(Mermaid)
flowchart TD
  A["确认 MySQL 8.4 服务与实际端口"] --> B["客户端连接指定端点"]
  B --> C{"认证是否成功"}
  C -->|"否"| D["核对账户与来源及错误信息"]
  C -->|"是"| E["查询版本与当前数据库"]
  E --> F["创建独立练习库并选择它"]
  F --> G["建表写入 hello 并重新查询"]
  G --> H["退出客户端后重新连接复核"]

按顺序看,每一步做了什么

  1. 核对服务名、主机和实际端口,确认没有误连另一实例。
  2. 通过交互密码连接并记录服务端版本。
  3. 创建明确独立的练习库,用当前库查询确认 SQL 所处位置。
  4. 写入一条测试数据,退出重连后再次读取,观察连接生命周期与数据生命周期的差别。

03对照实现代码

DriverManager 如何把 JDBC URL 交给已注册驱动 (新标签页)↗

OpenJDK 17u,jdk-17.0.16+8 · java.sql.DriverManager#getConnection(String, Properties, Class<?>)

已核验所链接文件和私有工作方法。下面为原创 Java 教学模型,保留逐驱动尝试、null 表示不适配、保留首个 SQL 异常三个局部机制;省略真实注册、类加载器可见性、权限和连接超时。它不执行网络 I/O,也不是 MySQL 内核源码。

核心机制代码 · java
import java.sql.SQLException;
import java.util.List;
class SourceModel {
  interface Adapter { String open(String url) throws SQLException; }
  static String choose(List<Adapter> visibleAdapters, String url) throws SQLException {
    if (url == null) throw new SQLException("missing URL"); // 入口先拒绝空地址
    SQLException firstFailure = null; // 记住第一个真实连接失败
    for (Adapter adapter : visibleAdapters) {
      try {
        String result = adapter.open(url); // 驱动自己识别协议前缀
        if (result != null) return result; // null 代表该驱动不适配
      } catch (SQLException failure) {
        if (firstFailure == null) firstFailure = failure;
      }
    }
    if (firstFailure != null) throw firstFailure; // 不能把真实失败抹掉
    throw new SQLException("no matching adapter");
  }
}

真实 DriverManager 的公开重载最后进入带调用者信息的工作方法。它先确定可见的类加载器范围并确保驱动已初始化,然后遍历注册驱动。这说明驱动选择依赖 Java 运行时能看到的实现,不是读取了一个以 jdbc 开头的字符串就能自动下载并安装数据库驱动。

每个合适的驱动接收 URL 和属性。如果该驱动不理解 URL,可以返回 null,让后续驱动继续尝试;理解 URL 却发生连接错误时则可能抛 SQLException。教学模型把成功连接简化成字符串,刻意保留这两类不同结果,帮助解释协议不匹配与真实连接失败为何不能混成一种诊断。

真实方法会记住遇到的首个 SQL 异常。如果遍历结束仍没有连接,存在该异常时把它抛回,否则给出没有合适驱动的错误。这个分支是读源码的关键:最后抛什么由已经发生的过程决定,不能只看最终异常类型就忽略其消息、原因链和之前的环境。

JDK 选好驱动后,具体驱动才继续进行数据库握手和认证。这一层不能证明表存在、隔离级别正确或数据已经保存到磁盘。读完客户端部分,还要到 MySQL 服务端资料检查相应机制,不要把 Java 的驱动选择循环当成数据库执行算法。

代码先调用谁,再调用谁

  1. 应用调用 DriverManager.getConnection。
  2. 工作方法准备可见驱动集合并初始化注册。
  3. 逐个调用 Driver.connect,区分不适配、连接成功和异常。
  4. 返回连接,或依据累积结果抛出可定位的失败。

04动手写一个例子

解析受限 JDBC 地址并验证连接端点

输入形如 jdbc:mysql://host[:port]/database 的字符串,返回主机、端口和库名。仅支持 ASCII 主机名及 IPv4 形式,不验证 DNS 存在性;库名限字母、数字和下划线,省略端口时用 3306。明确拒绝用户信息、查询参数、IPv6 与多主机语法。本题是配置校验练习,不是完整 Connector/J URL 解析器。

输入 1
jdbc:mysql://localhost/lab
输出 1
localhost:3306/lab
输入 2
jdbc:mysql://127.0.0.1:65535/lab_2
输出 2
127.0.0.1:65535/lab_2
输入 3
jdbc:mysql://localhost:0/lab
输出 3
IllegalArgumentException
输入 4
jdbc:mysql://localhost/lab?password=x
输出 4
IllegalArgumentException

先检查固定协议前缀,再把余下输入划分为 authority 与数据库名。唯一斜线是这道受限语法的结构分界;如果没有斜线、数据库为空或还出现第二条路径,应立即拒绝,避免把拼错的地址悄悄解释成另一目标。

authority 内最多允许一个冒号。存在冒号时,右侧必须是十进制端口;不存在时使用默认值。主机与库名分别验证字符范围,因为它们承担不同角色。校验成功只证明输入属于定义的语法,不证明主机能解析或这个端口真的有服务。

端口先以 long 累积,并在每次加入数字后检查是否超过 65535,因此极长数字不会等到 int 溢出后才被发现。程序在 main 中执行正常、省略端口、最大端口、零端口、空库名与不支持语法等固定期望;出现错误立即抛 AssertionError,可用 javac --release 17 Main.java 后运行 java Main。

为什么这样写是对的扫描端口前缀后,value 精确等于已扫描十进制数字且始终不大于 65535;返回前所有字符都被分配到已验证的主机、端口或库名。

时间 O(n)额外空间 O(n)

每个输入字符只参与常数次扫描。substring 和返回字段保存与输入长度线性相关的字符,除输出外只用常数个索引与数值变量。

保存为 Main.java,运行 javac --release 17 -encoding UTF-8 Main.java,再运行 java Main。程序包含固定输入自测,断言失败时会抛出错误。

展开收起代码 · Main.java · 完整可运行程序Java · 53 行

长行可在代码区域内左右滚动,按 Tab 可把焦点移入代码区。

Main.java · 完整可运行程序 · Java
public class Main {
  record Endpoint(String host, int port, String database) {
    public String toString() { return host + ":" + port + "/" + database; }
  }
  static Endpoint parse(String input) {
    String prefix = "jdbc:mysql://";
    if (input == null || !input.startsWith(prefix)) throw new IllegalArgumentException();
    String rest = input.substring(prefix.length());
    int slash = rest.indexOf('/'); // 本题只接受一个数据库路径段
    if (slash <= 0 || slash != rest.lastIndexOf('/') || slash == rest.length()-1)
      throw new IllegalArgumentException();
    String authority = rest.substring(0, slash);
    String database = rest.substring(slash+1);
    if (!database.matches("[A-Za-z0-9_]+")) throw new IllegalArgumentException();
    int colon = authority.indexOf(':');
    if (colon != authority.lastIndexOf(':')) throw new IllegalArgumentException();
    String host = colon < 0 ? authority : authority.substring(0, colon);
    if (!host.matches("[A-Za-z0-9.-]+")) throw new IllegalArgumentException();
    int port = 3306; // 省略端口只使用本题公开的默认值
    if (colon >= 0) {
      String digits = authority.substring(colon+1);
      if (digits.isEmpty()) throw new IllegalArgumentException();
      long value = 0;
      for (char ch : digits.toCharArray()) {
        if (ch < '0' || ch > '9') throw new IllegalArgumentException();
        value = value * 10 + ch - '0'; // 上次迭代已保证 value 有界
        if (value > 65535) throw new IllegalArgumentException();
      }
      if (value == 0) throw new IllegalArgumentException();
      port = (int) value;
    }
    return new Endpoint(host, port, database);
  }
  static void expect(String input, String expected) {
    if (!parse(input).toString().equals(expected)) throw new AssertionError(input);
  }
  static void reject(String input) {
    try { parse(input); throw new AssertionError("应拒绝: " + input); }
    catch (IllegalArgumentException expected) { /* 明确期望的错误 */ }
  }
  public static void main(String[] args) {
    // 固定期望覆盖正常、空值和错误边界,失败立即中断验证
    expect("jdbc:mysql://localhost/lab", "localhost:3306/lab");
    expect("jdbc:mysql://127.0.0.1:65535/lab_2", "127.0.0.1:65535/lab_2");
    expect("jdbc:mysql://db:3307/demo", "db:3307/demo");
    reject("jdbc:mysql://db:0/demo");
    reject("jdbc:mysql://db:999999999999/demo");
    reject("jdbc:mysql://db/");
    reject("jdbc:mysql://db/demo?password=x");
    reject("");
    System.out.println("PASS 8 endpoint tests");
  }
}

这些特殊情况也要试一试

  • 空输入和错误协议前缀必须拒绝。
  • 端口 1 与 65535 合法,0、负数、非数字和过大数字不合法。
  • 实际 Connector/J 支持更丰富语法,本题拒绝它们不表示驱动也拒绝。
进阶选读 · 生产拓展:多主机连接串与秘密分离

场景应用需要故障切换地址、IPv6 和驱动属性时,受限解析器无法覆盖真实协议。

做法交给版本明确的官方驱动解析,应用只验证业务允许的目标和属性;密码通过受控配置来源提供。维护解析后的端点清单与脱敏诊断信息,分别验证格式、解析结果和实际连接。

复杂度文本解析通常与输入长度相关;逐端点连接成本另含网络超时,不能合并为纯 O(n) 字符扫描。

好处与代价完整语法提高兼容性,也扩大配置与误连风险;限制语法更容易审计,但必须在接口契约中公开限制。

05项目里怎么用

从练习走向应用时,应创建最小权限的专用账户,不让业务常态使用管理员凭据。连接配置需要区分开发、测试与生产,并避免在异常消息或日志中输出完整带秘密 URL。端口选用非默认值时,客户端、应用配置和监控检查必须一致,不能只修正某一个工具后宣布所有链路完成。

连接成功之后还要验证实际语句、当前库、字符集与业务读写权限。尤其在一台机器运行多个实例时,同名表很容易让错误环境看起来也能工作。把服务端版本、数据库名和有限环境标识纳入启动诊断有助于排查,但应避免把数据库内部地址无条件暴露给匿名接口。

一条短查询成功,只证明这次连接与查询可用,不证明高并发时连接池够用,也不证明备份能恢复。先保存这个最小成功用例,再逐步加入连接池、迁移和恢复演练;每增加一步都保留原检查,失败时才容易找到哪项新变化引起问题。

容易踩的坑

  • 把 SQL 输入 PowerShell,或把系统命令输入 mysql 提示符,属于执行环境混淆。
  • 重装软件前未检查真实服务与端口,会破坏已有现场且未必解决问题。
  • 将密码直接接在命令行参数后,可能进入历史或进程信息。
  • 客户端正常退出不等于数据库被关闭,关闭服务也不等于删除数据。

几种做法,怎么选

表格有四列,窄屏可左右滑动查看代价和适用条件。

方案优势代价与限制适用条件
本机安装服务运行入口直观,便于理解 Windows 服务与目录。版本和数据目录长期存在,需要自行维护隔离与升级。先建立稳定的单机学习环境。
容器练习实例易于创建明确隔离的版本和运行实例。需要额外理解端口映射、卷和容器生命周期。已经掌握容器基础或需要多版本实验。
共享现有实例中的专用库减少安装步骤,能复用已有服务。账户权限与命名空间必须隔离,不能做破坏性故障演练。明确获授权且能控制实验范围的环境。

06检验是否读懂了

先自己想、自己写,再展开答案核对。场景题是假设的练习情境;遇到还没学过的内容,可以做完基础后再回来。

先用自己的话解释

01客户端退出后为什么 hello 行仍可能存在?

展开参考答案与推导

客户端连接与服务端数据生命周期不同。已提交写入由服务端维护,退出会话不等于删除表或停止服务;是否经历故障后仍可恢复还需讨论事务与持久化。

02没有合适 JDBC 驱动与 Access denied 是否属于同一层?

展开参考答案与推导

前者主要指 Java 运行时没有找到可处理 URL 的可见驱动,后者涉及到达数据库认证或权限检查后的失败,应分别核对依赖与身份配置。

03为什么要先 SELECT DATABASE()?

展开参考答案与推导

连接可以没有选定默认库,也可能选中了错误命名空间。显式检查能在建表前发现误连,防止在同名表存在时被表面成功误导。

换个情况,还会处理吗

01图形客户端能查数据,应用启动失败,如何缩小范围?

展开参考答案与推导

对比实际主机、端口、账户、库名和服务端版本,再核对应用驱动、运行时与密码来源。使用应用同一配置执行最小 JDBC 验证,不能只凭图形界面结果证明应用路径。

02连接拒绝后是否应立即重置数据库密码?

展开参考答案与推导

先检查端点与监听进程,连接拒绝通常先指向建立连接阶段。只有已到达身份检查并有对应证据时,才继续排查密码与账户来源。

03发现练习库名称已经存在,怎么处理?

展开参考答案与推导

先确认用途;用途不明就换一个新名字,不删除、不重新初始化,也不把现有数据当作可随意覆盖的练习材料。

写代码试一试

01给解析器增加允许端口集合校验。

输入 / 条件
地址端口为 3307,允许集合为 {3306,3307}
输出 / 预期
接受;端口 4406 则拒绝

提示 格式校验之后再做策略校验。

展开参考答案与推导

先得到 Endpoint,再检查端口集合。区分语法不合法与策略不允许,使以后调整允许范围不必修改解析状态机。

02如何测试极长端口输入而不发生数值溢出?

输入 / 条件
jdbc:mysql://db:999999999999999999/x
输出 / 预期
IllegalArgumentException

提示 不要先把整个串直接累积到 int。

展开参考答案与推导

每加入一个数字后立即检查上限,保证下一步乘十前仍处于小范围;也可以使用有溢出检查的解析方式,但错误应归一为可解释的配置错误。

03模拟首个驱动不适配、第二个失败、第三个成功。

输入 / 条件
返回值依次为 null、SQLException、connected
输出 / 预期
返回 connected

提示 失败并不一定立即结束适配遍历。

展开参考答案与推导

用三个无网络的 Adapter 构造测试。循环继续尝试可见驱动,成功时返回;只有全部失败时才抛已保存的首个异常。

读完之后,独立完成

课后作业:自己做一遍

本篇共 10 道作业,先完成 8 道基础与综合任务,再按前置知识挑战进阶题。其中包含 1 道思维拓展,试着换个条件,看看原来的办法是否还管用。不附参考答案。

这次练什么

能在独立练习库创建表、插入并查询一行,重新连接后说明当前数据库和实际连接端口。

本篇重点加练

重点加练真实端点与当前数据库,建立每次操作前确认目标环境的习惯。

  • Windows 服务、安装路径和端口
  • CREATE DATABASE 与 USE

重点内容会多练几次。先说清楚怎么做,再试试空数据、出错或条件改变时会发生什么。

先自己做,卡住时记下问题,再回来查。问答题写清“为什么、什么时候适用”;动手题留下输入、输出和运行步骤,方便下次重做。

基础必做

  1. 作业 01原理问答

    根据本机情况列出 MySQL Server、命令行客户端与 Configurator 的职责;若已有实例,记录其来源和版本,不重新初始化数据目录。说明哪些组件安装完成仍不足以证明能查询。

    提交内容
    组件关系图和环境核验表。
    怎样算完成
    • 服务与客户端分开
    • 复用既有实例不破坏数据

    练到的知识点服务端与客户端的职责 · MSI 安装与 Configurator 配置

  2. 作业 02排错实验

    读取真实 Windows 服务名、安装路径与监听端口,使用交互密码方式连接;在独立尝试中仅修改本次客户端连接命令的端口参数,使用一个确认未被占用的本地端口,不修改服务配置。记录错误后以正确端口重新连接。

    提交内容
    脱敏连接命令、服务信息和两次连接记录。
    怎样算完成
    • 密码不出现在命令或截图中
    • 连接故障有具体阶段证据

    练到的知识点Windows 服务、安装路径和端口 · 交互密码输入与连接错误分类

  3. 作业 03代码推演

    在 mysql 提示符中观察一条尚未以分号结束的 SELECT,再完成它;随后在专用练习库切换前后查询当前库名。记录提示符和 SQL 的执行边界。

    提交内容
    交互记录与提示符说明。
    怎样算完成
    • Shell 命令和 SQL 环境区分
    • 创建库与选择库是独立步骤

    练到的知识点SQL 分号与客户端提示符 · CREATE DATABASE 与 USE

  4. 作业 04设计评审

    同一电脑装有两个版本的 mysql.exe,命令行客户端版本与服务器版本可能不同。制定确认实际连接端点和服务端身份的只读检查。

    提交内容
    客户端/服务端核验表。
    怎样算完成
    • 安装路径与连接目标分开
    • 证据可对应本次会话

    练到的知识点Windows 服务、安装路径和端口

综合应用

  1. 作业 05编程实践

    创建本题独有的学习记录库和表,保存标题与学习日期,插入三条自定记录后按条件查询;退出并重新连接,再验证仍能找到自己的练习数据。

    提交内容
    SQL 文件、自写空结果/多行/重连检查及执行证据。
    怎样算完成
    • 先核对当前库再写入
    • 证据包含真实查询结果
    • 只操作明确命名的练习资源

    练到的知识点CREATE DATABASE 与 USE · 库表层次与首条查询

  2. 作业 06设计评审

    后续 Java 程序只需读写本题学习记录表,团队拟直接复制管理账号配置。写出应用所需操作清单、账号权限边界和配置脱敏要求。

    提交内容
    最小操作权限表与连接验收计划。
    怎样算完成
    • 权限来自业务需要
    • 凭据与日志边界清楚

    练到的知识点管理账号与后续应用账号的边界

  3. 作业 07排错实验

    用正确端口连接本机已有练习实例,不在连接命令指定数据库;查询当前库后显式切换题目专用库,再重连观察。全程不改变服务配置。

    提交内容
    脱敏命令、自写端点/当前库检查表及运行记录。
    怎样算完成
    • 会话状态每次重新核验
    • 只在确认的练习库执行后续操作

    练到的知识点Windows 服务、安装路径和端口 · CREATE DATABASE 与 USE

  4. 作业 08代码推演

    终端 A 选中练习库,终端 B 刚登录未执行 USE。预测两个终端执行不带库名前缀的查询需要哪些前提,再在专用库做只读验证。

    提交内容
    双会话记录与作用域说明。
    怎样算完成
    • 选库状态按会话追踪
    • 不通过写入未知目标验证假设

    练到的知识点CREATE DATABASE 与 USE

进阶挑战 · 掌握前置后选做

  1. 作业 09面试场景

    完成 JDBC 基础后:一台电脑存在两个 MySQL 实例,两边都有 study_note 表。设计启动诊断与只读核验,确认应用连接到期望实例和练习库。

    提交内容
    端点/实例/库核验清单及脱敏诊断样例。
    怎样算完成
    • 同名表不被当作正确环境证明
    • 工具连接和应用连接分别验证

    练到的知识点服务端与客户端的职责 · Windows 服务、安装路径和端口 · 交互密码输入与连接错误分类 · 管理账号与后续应用账号的边界

思维拓展

先写出你的猜想,再用例子或实验验证。答案可以不同,但要说清依据、适用情况,以及还有什么没弄懂。

  1. 作业 10思维拓展 · 反例构造

    有人看到名为 first_note 的表就认定连接正确。构造两个可区分的环境草图,列出最少只读证据判断是否是预期端点和库;无需安装第二实例。

    提交内容
    双环境样本及只读核验流程。
    怎样算完成
    • 名称相同与环境身份分开
    • 每个结论有对应证据来源

    练到的知识点Windows 服务、安装路径和端口 · CREATE DATABASE 与 USE

完成后,再检验一次

给每题标记“独立完成 / 查阅后完成 / 尚未完成”。查过资料或没做出的题,记下卡在哪里。隔一天换一组输入再试,能解释结果和出错原因,再把这个知识点标为掌握。

继续阅读

先看能帮你完成当前练习的部分。例子跑通后,再读更深入的解释。

打开资料库,找下一份学习材料 ↗