一、简介

       在开发中,部分开发者会选择在虚拟机的 Docker 容器中部署 MySQL(兼顾环境隔离与资源轻量性),但新手常因 “容器网络隔离、权限配置、跨环境连通” 等问题,卡在 PyCharm 与容器化 MySQL 的对接环节。本文关注 “物理机 PyCharm → 虚拟机 → Docker 容器 MySQL” 的三层架构,详细拆解从 Docker 端 MySQL 的端口映射、远程权限配置,到虚拟机网络适配,再到 PyCharm 的数据库连接与验证的完整流程,同时针对 “连接被拒、权限错误” 等高频问题提供排障方案,帮助开发者快速实现 PyCharm 对容器化 MySQL 的可视化操作与代码调用,打通开发环境的数据链路。

二、过程

2.1 准备

(1)pycharm

(2)虚拟机Ubuntu

(3)docker

(4)MySQL(使用MySQL官方的docker镜像)

2.2 拉取MySQL官方的docker镜像

镜像加速

sudo vim /etc/docker/daemon.json

# 输入以下
{
  "registry-mirrors": [
    "https://dockerproxy.com",
    "https://hub-mirror.c.163.com",
    "https://docker.mirrors.ustc.edu.cn"
  ]
}

sudo systemctl daemon-reload  # 重新加载配置
sudo systemctl restart docker  # 重启 Docker 服务

拉取

zky@zky-virtual-machine:~$ docker pull mysql:8.4.7
8.4.7: Pulling from library/mysql
023a182c62a0: Pull complete 
f5f78fcd9ccb: Pull complete 
494c372d15c3: Pull complete 
0d0f66273639: Pull complete 
6d7d6105636e: Pull complete 
3763684269ad: Pull complete 
f7c524da3882: Pull complete 
824d865d5643: Pull complete 
270bbb610640: Pull complete 
fe8b60e8a15a: Pull complete 
Digest: sha256:b306273d4d36bc1a7f265130c3dd93c0462253af7634203e569add0403a7b273
Status: Downloaded newer image for mysql:8.4.7
docker.io/library/mysql:8.4.7
zky@zky-virtual-machine:~$ 

查看镜像

zky@zky-virtual-machine:~$ docker images
REPOSITORY                            TAG       IMAGE ID       CREATED        SIZE
emqx/emqx-enterprise                  6.0.1     8c34ff14ce29   2 weeks ago    265MB
mysql                                 8.4.7     67471052edd5   5 weeks ago    788MB

2.3 基于MySQL官方镜像运行一个MySQL容器

zky@zky-virtual-machine:~$ docker run -itd --name mysql_8_4_7 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:8.4.7
396b74a695004c17df6624988069c81c7dc524cdaf5da3965f5e23271230669b
zky@zky-virtual-machine:~$ docker ps
CONTAINER ID   IMAGE         COMMAND                   CREATED         STATUS         PORTS                                                    NAMES
396b74a69500   mysql:8.4.7   "docker-entrypoint.s…"   9 seconds ago   Up 8 seconds   0.0.0.0:3306->3306/tcp, [::]:3306->3306/tcp, 33060/tcp   mysql_8_4_7
zky@zky-virtual-machine:~$ 

2.4 进入MySQL容器内部

docker exec -it mysql_8_4_7 /bin/bash

2.5 在容器里登录进入MySQL终端

密码就是运行容器时设置的密码

bash-5.1# mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.4.7 MySQL Community Server - GPL

Copyright (c) 2000, 2025, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

2.6 Mysql help

mysql> help

For information about MySQL products and services, visit:
   http://www.mysql.com/
For developer information, including the MySQL Reference Manual, visit:
   http://dev.mysql.com/
To buy MySQL Enterprise support, training, or other products, visit:
   https://shop.mysql.com/

List of all MySQL commands:
Note that all text commands must be first on line and end with ';'
?         (\?) Synonym for `help'.
clear     (\c) Clear the current input statement.
connect   (\r) Reconnect to the server. Optional arguments are db and host.
delimiter (\d) Set statement delimiter.
edit      (\e) Edit command with $EDITOR.
ego       (\G) Send command to mysql server, display result vertically.
exit      (\q) Exit mysql. Same as quit.
go        (\g) Send command to mysql server.
help      (\h) Display this help.
nopager   (\n) Disable pager, print to stdout.
notee     (\t) Don't write into outfile.
pager     (\P) Set PAGER [to_pager]. Print the query results via PAGER.
print     (\p) Print current command.
prompt    (\R) Change your mysql prompt.
quit      (\q) Quit mysql.
rehash    (\#) Rebuild completion hash.
source    (\.) Execute an SQL script file. Takes a file name as an argument.
status    (\s) Get status information from the server.
system    (\!) Execute a system shell command, if enabled
tee       (\T) Set outfile [to_outfile]. Append everything into given outfile.
use       (\u) Use another database. Takes database name as argument.
charset   (\C) Switch to another charset. Might be needed for processing binlog with multi-byte charsets.
warnings  (\W) Show warnings after every statement.
nowarning (\w) Don't show warnings after every statement.
resetconnection(\x) Clean session context.
query_attributes Sets string parameters (name1 value1 name2 value2 ...) for the next query to pick up.
ssl_session_data_print Serializes the current SSL session data to stdout or file

For server side help, type 'help contents'

mysql> 

2.6.1 开头的 3 个链接:获取更全面的帮助

这部分是 MySQL 官方提供的「外部帮助渠道」,适合需要深度学习或解决复杂问题时参考:

链接 用途
http://www.mysql.com/ MySQL 官方主页,可了解产品、服务、最新动态(如新版本特性)
http://dev.mysql.com/ 开发者文档中心,核心是 MySQL Reference Manual(MySQL 参考手册),包含所有 SQL 语法、函数、配置参数的详细说明(最权威的学习资料)
https://shop.mysql.com/ 购买 MySQL 企业版支持、培训等商业服务(个人 / 开发环境用免费社区版即可,无需关注)

注:如果部分读者有sql sever的语法基础,会轻松一点点

2.6.2 核心使用规则(关键提示)

Note that all text commands must be first on line and end with ';'

翻译 + 解读:所有「文本命令」(包括 SQL 语句、客户端命令)必须放在行首,且以 分号 ; 结尾—— 这是 MySQL 命令行的核心语法规则,新手最容易踩坑!

  • 示例 1(正确):SELECT * FROM user;(SQL 语句以分号结尾)
  • 示例 2(错误):mysql> select * from user(没加 ;,MySQL 会认为命令没输完,一直等待输入,直到你补加分号并回车)
  • 例外:部分客户端命令(如 \q 退出、\c 清除输入)可不用分号结尾,直接回车生效。

2.6.3 常用 MySQL 客户端命令详解(重点必看)

下面列出 最常用的命令(按使用频率排序),包括缩写、作用和使用场景,帮你快速上手:

命令(全称 / 缩写) 作用 实用场景示例
help / \? 显示当前帮助文档(就是你看到的内容) 忘记命令时快速查询:mysql> \?
clear / \c 清除当前输入的未完成命令 输错 SQL 不想执行时:mysql> selec * from user; \c(回车后清空错误输入,回到干净的 mysql> 提示符)
exit / quit / \q 退出 MySQL 命令行,返回系统终端 操作完成后退出:mysql> \q 或直接 mysql> exit
use / \u 切换到指定数据库(核心命令) 想操作 testdb 数据库时:mysql> use testdb;(提示 Database changed 表示切换成功)
status / \s 查看 MySQL 服务器状态和客户端信息 检查连接状态、数据库版本、当前用户等:mysql> \s(会显示如 MySQL 版本、当前数据库、字符集等信息)
source / \. 执行本地的 SQL 脚本文件(批量执行 SQL) 导入备份的 SQL 文件:mysql> source /home/zky/backup.sql;(脚本路径要写绝对路径,以分号结尾)
ego / \G 垂直显示查询结果(替代 ; 结尾) 查询字段多的表时更易读:mysql> SELECT * FROM user \G(结果按「字段名:值」垂直排列,避免横向挤在一起)
delimiter / \d 修改 SQL 语句的结束符(默认是 ; 定义存储过程 / 函数时用(避免和函数内的 ; 冲突):mysql> \d //(后续 SQL 以 // 结尾才执行)
system / \! 执行系统终端命令(如 ls、pwd,需启用) 不用退出 MySQL 查看本地文件:mysql> \! ls /home/zky(查看该目录下的文件)
tee / \T 将后续所有操作和结果写入文件(日志记录) 保存查询结果到文件:mysql> \T /home/zky/query_log.txt(之后的所有输入和输出都会追加到该文件)
charset / \C 切换字符集(如 UTF-8) 解决中文乱码时:mysql> \C utf8mb4(切换到支持所有中文的字符集)

2.6.4 如何获取「SQL 语法 / 函数」的帮助(服务器端帮助)

当前 help 显示的是「客户端命令帮助」(比如怎么退出、怎么切换数据库),如果想查 SQL 语句语法(如 SELECTINSERT)、函数(如 COUNT()DATE()),需要用下面的方法:

  1. 先输入 help contents,查看服务器端帮助的分类:

    mysql

    mysql> help contents;
    

    会输出分类列表,比如:

    plaintext

    Data Definition
    Data Manipulation
    Data Types
    Functions and Operators
    ...
    
  2. 按分类查询具体内容,比如:

    • 查 SELECT 语法:mysql> help SELECT;
    • 查 COUNT() 函数:mysql> help COUNT;
    • 查数据类型:mysql> help Data Types;

这是 MySQL 内置的「SQL 帮助手册」,不用联网就能快速查询语法,非常实用。

2.6.5 总结

这个 help 输出的核心价值是:

  1. 告诉新手 MySQL 命令行的「使用规则」(分号结尾、行首命令);
  2. 提供「客户端常用命令」(退出、切换数据库、执行脚本等),帮你快速操作;
  3. 指引获取更深入的帮助(官方文档、SQL 语法帮助)。

新手优先掌握这几个命令就能满足日常使用:

  • 切换数据库:use 数据库名;
  • 退出:\q 或 exit
  • 清除错误输入:\c
  • 执行 SQL 脚本:source 脚本路径;
  • 垂直显示结果:查询语句 \G

如果想查具体 SQL 语法(比如怎么建表、怎么插入数据),直接输入 help 语法名(如 help CREATE TABLE;)即可。

2.7 初步操作数据库MySQL

注意:分号结尾

2.7.1 建库

# 查看库 本身自带4个库
show databases;

# 建立数据库
create database My_Study_DB_1;
mysql> create database My_Study_DB_1;
Query OK, 1 row affected (0.01 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| My_Study_DB_1      |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.01 sec)

2.7.2 切换到库

mysql> use My_Study_DB_1
Database changed

后面的操作全是对My_Study_DB_1数据库操作

查看当前处于哪个数据库

SELECT DATABASE();

或者

status;

2.7.3 建表

mysql> create table student (
    -> id int primary key auto_increment,
    -> name varchar(50) not null,
    -> age int default 0,
    -> gender varchar(10) default 'unknown'
    -> );
Query OK, 0 rows affected (0.02 sec)

看表

mysql> show tables;
+-------------------------+
| Tables_in_My_Study_DB_1 |
+-------------------------+
| student                 |
+-------------------------+
1 row in set (0.00 sec)

mysql> SELECT * FROM student;
+----+----------+------+--------+
| id | name     | age  | gender |
+----+----------+------+--------+
|  1 | zhangsan |   20 | man    |
|  2 | lisi     |   21 | woman  |
|  3 | wangwu   |   22 | man    |
+----+----------+------+--------+
3 rows in set (0.00 sec)

2.7.4 增删改查

(1)增
mysql> insert into student (id, name, age, gender) values (1, 'zhangsan', 20, 'man');
Query OK, 1 row affected (0.02 sec)
(2)删

删除数据(同样必须加 where 条件,否则删全表!):

# 删除id=3的学生(按主键删除最安全,主键唯一)
mysql> delete from student where id=3;

提示 Query OK, 1 row affected (0.01 sec) 表示删除成功。

mysql> delete from student where id=3;
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM student;
+----+----------+------+--------+
| id | name     | age  | gender |
+----+----------+------+--------+
|  1 | zhangsan |   20 | man    |
|  2 | lisi     |   21 | woman  |
+----+----------+------+--------+
2 rows in set (0.00 sec)
(3)改

修改已有数据(必须加 where 条件,否则改全表!):

# 把李四的性别改成“男”,年龄改成20
mysql> update student set gender='男', age=20 where name='李四';

提示 Query OK, 1 row affected (0.01 sec) 表示修改成功(1 行数据被修改)。

mysql> SELECT * FROM student;
+----+----------+------+--------+
| id | name     | age  | gender |
+----+----------+------+--------+
|  1 | zhangsan |   20 | man    |
|  2 | lisi     |   21 | woman  |
+----+----------+------+--------+
2 rows in set (0.00 sec)

mysql> update student set gender='man', age=30 where name='lisi';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT * FROM student;
+----+----------+------+--------+
| id | name     | age  | gender |
+----+----------+------+--------+
|  1 | zhangsan |   20 | man    |
|  2 | lisi     |   30 | man    |
+----+----------+------+--------+
2 rows in set (0.00 sec)

mysql> 
(4)查

查看表中的数据(最常用,灵活度最高):

# 1. 查询所有数据(* 表示所有字段)
mysql> select * from student;
# 输出结果(按插入顺序显示):
+----+--------+-----+--------+
| id | name   | age | gender |
+----+--------+-----+--------+
|  1 | 张三   |  20 | 男     |
|  2 | 李四   |  19 | 未知   |
|  3 | 王五   |  21 | 女     |
+----+--------+-----+--------+

# 2. 条件查询(只查年龄>19的学生)
mysql> select name, age from student where age > 19;  # 只显示姓名和年龄字段

# 3. 排序查询(按年龄降序排列)
mysql> select * from student order by age desc;

嵌套查询例子

有两张关联表:

  • student:存储学生基础信息(id、name、age、gender)
  • score:存储学生成绩(通过 student_id 和学生表关联)
mysql> SELECT * FROM score
    -> ;
+----+------------+---------+-------+
| id | student_id | subject | score |
+----+------------+---------+-------+
|  1 |          1 | math    |    50 |
|  2 |          1 | English |    55 |
|  3 |          2 | math    |    80 |
|  4 |          2 | English |    85 |
+----+------------+---------+-------+
4 rows in set (0.00 sec)

mysql> SELECT * FROM student;
+----+----------+------+--------+
| id | name     | age  | gender |
+----+----------+------+--------+
|  1 | zhangsan |   20 | man    |
|  2 | lisi     |   30 | man    |
+----+----------+------+--------+
2 rows in set (0.00 sec)


mysql> SELECT * FROM student WHERE id IN ( SELECT student_id FROM score WHERE subject = 'math' AND score >= 80 );
+----+------+------+--------+
| id | name | age  | gender |
+----+------+------+--------+
|  2 | lisi |   30 | man    |
+----+------+------+--------+
1 row in set (0.01 sec)

mysql> 

2.8 使用pycharm对接

2.8.1 打开数据源

下载缺少的驱动

2.8.2 配置连接

主机位置填虚拟机的ip,虚拟机里的docker里的数据库的端口已经映射到了虚拟机的端口了

2.8.3 查看数据库

注:如果你有在Windows下使用过SQL Server的经验,那么会好上手一些

输入语句,再点击绿色三角按钮运行这个语句

show databases;

2.8.4 查表

2.9 写一个简单的python程序来使用这个数据库

2.9.1 到终端激活虚拟环境安装库

 pip3 install pymysql -i https://mirrors.aliyun.com/pypi/simple/

2.9.2 代码

import pymysql
from pymysql.cursors import DictCursor  # 用于将查询结果转为字典(更易读)

def main():
    # 1. 数据库连接参数(根据你的实际环境修改!)
    config = {
        "host": "192.168.123.3",  # 虚拟机的 IP 地址(必须替换为你的虚拟机实际 IP)
        "port": 3306,            # 端口(之前映射的 3306)
        "user": "root",          # MySQL 用户名
        "password": "111111",    # 密码(启动容器时设置的)
        "database": "My_Study_DB_1",  # 数据库名
        "charset": "utf8mb4",    # 字符集(支持中文和 emoji)
        "cursorclass": DictCursor  # 让查询结果以字典形式返回
    }

    # 2. 连接数据库并操作
    try:
        # 建立连接
        conn = pymysql.connect(**config)
        print("数据库连接成功!")

        # 创建游标(用于执行 SQL)
        cursor = conn.cursor()

        # 3. 示例 1:查询 student 表的所有数据
        print("\n----- 查询 student 表所有数据 -----")
        sql_query = "SELECT * FROM student;"
        cursor.execute(sql_query)  # 执行查询
        results = cursor.fetchall()  # 获取所有结果
        for row in results:
            # 以字典形式输出每条数据(键是字段名,值是数据)
            print(f"ID: {row['id']}, 姓名: {row['name']}, 年龄: {row['age']}, 性别: {row['gender']}")

        # 4. 示例 2:插入一条新数据到 student 表
        print("\n----- 插入新数据 -----")
        new_student = {
            "id": 3,
            "name": "wangwu",
            "age": 22,
            "gender": "man"
        }
        sql_insert = """
            INSERT INTO student (id, name, age, gender) 
            VALUES (%(id)s, %(name)s, %(age)s, %(gender)s);
        """
        cursor.execute(sql_insert, new_student)  # 执行插入(参数用字典传入,避免 SQL 注入)
        conn.commit()  # 提交事务(插入/更新/删除必须提交才会生效)
        print(f"成功插入新学生:{new_student['name']}")

        # 5. 再次查询,验证插入结果
        print("\n----- 插入后的数据 -----")
        cursor.execute(sql_query)
        for row in cursor.fetchall():
            print(f"ID: {row['id']}, 姓名: {row['name']}, 年龄: {row['age']}, 性别: {row['gender']}")

    except pymysql.MySQLError as e:
        # 出错时回滚事务(避免部分插入)
        if 'conn' in locals():
            conn.rollback()
        print(f"数据库操作失败:{e}")  # 打印错误信息(方便排查)
    finally:
        # 关闭连接(无论成功失败都要关闭)
        if 'conn' in locals() and conn.open:
            cursor.close()
            conn.close()
            print("\n数据库连接已关闭")

if __name__ == "__main__":
    main()

2.9.3 实验现象

注:这里只是简单演示方法,一切的复杂项目都是从基底一步步搭建起来的,洞彻增删查改的本质,掌握好的逻辑思维,构建严谨且漂亮的项目。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐