用pymysql操作本地MySQL数据库与用pymongo操作本地MongoDB数据库

前置知识

对于IP地址,大家并不陌生,特别是在网络访问中我们会经常使用到(平时对域名如百度的www.baidu.com的访问,本质就是对域名所绑定的IP地址的访问),那么IP地址是什么呢?

首先,我们要知道网络中的相互访问其实就是在进行两者间的数据传递。就如同送快递一样,快递发出只有知道你的住址信息,才能将快递送到你的手中。而在网络访问时,只有知道你在网络中的地址信息,才能将数据发送到你的设备上。所以,IP地址就是你在网络中的地址信息。与你现实地址不同的是,你的现实地址使用文字表示,而你在网络中的地址(IP地址)是用二进制数字表示的。

一般我们会将网络划分公网(连Internet的)内网

公有IP地址

一般称公网中的IP地址为公有地址。公有地址由Inter NIC(因特网信息中心)负责,这些IP地址分配给注册并向Inter NIC提出申请的组织机构。公有地址是全球唯一的,公网中不可能存在两个相同的IP地址

范围:除了私有地址以外的地址,都属于公有地址

私有IP地址

一般称内网(即局域网)中的IP地址为私有地址。私有地址是非注册地址,用于组织机构内部使用。私有地址的范围如下:

  • A类IP地址中:10.0.0.0–10.255.255.255
  • B类IP地址中:172.16.0.0–172.31.255.255
  • C类IP地址中:192.168.0.0–192.168.255.255

私有地址与公有地址不同,并不是由Internet分配的,是不允许出现在Internet中的,我们在公网中是看不到私有IP地址的,并且公有地址也不会使用上述的三类地址。所以,私有地址是不能直接与Internet连接的。

而如果想用私有地址与Internet连接来访问公网,那该怎么做?这就需要将私有IP地址转换成公网IP地址,与外部连接。所以,我们平时使用的路由器中会装有一个叫做 NAT(网络地址转换) 的软件,我们的路由器中会至少会有一个有效的公网IPNAT会将我们的私有地址转成路由器中的公网IP与外部Internet连接。而同样的,因为使用的是路由器中的公共的公网IP来连接Internet,所以这个内网中的PC在Internet中显示的都是路由器的公共IP,这样做不仅提供了一定程度的安全,也可以有效的减缓可用的IP地址空间的枯竭问题。(像我们学校或者公司的内网一般都是这么做的)

另外还有一点,在同一个局域网内,IP地址是唯一的;但是在不同的局域网内,IP地址是可以重复出现的。

举个小例子:局域网A中,有个主机的IP地址192.168.10.128,那么绝不可能在局域网A中还有其他主机的IP地址192.168.10.128。但是在局域网B中却可以有主机的IP地址也是192.168.10.128
如果局域网A中的192.168.10.128主机局域网B中的192.168.10.128主机通信,不会冲突吗?不会,因为上述说过,它们最终都是使用路由器中的公网IP来连接外网的,而公网IP是全球唯一的。

localhost、127.0.0.1和0.0.0.0和本机IP的区别

localhost

localhost其实是域名,一般windows系统默认将localhost指向127.0.0.1,但是localhost并不等于127.0.0.1localhost指向的IP地址是可以配置的

127.0.0.1

首先我们要先知道一个概念,凡是以127开头的IP地址,都是回环地址(Loop back address),其所在的回环接口一般被理解为虚拟网卡,并不是真正的路由器接口。

所谓的回环地址,通俗的讲,就是我们在主机上发送给127开头的IP地址的数据包会被发送的主机自己接收,根本传不出去,外部设备也无法通过回环地址访问到本机。

小说明:正常的数据包会从IP层进入链路层,然后发送到网络上;而给回环地址发送数据包数据包会直接被发送主机的IP层获取,后面就没有链路层他们啥事了。

127.0.0.1作为{127}集合中的一员,当然也是个回环地址。只不过127.0.0.1经常被默认配置为localhostIP地址
一般会通过ping 127.0.0.1来测试某台机器上的网络设备是否工作正常。

0.0.0.0

首先,0.0.0.0是不能被ping通的。在服务器中,0.0.0.0并不是一个真实的的IP地址,它表示本机中所有的IPV4地址。监听0.0.0.0的端口,就是监听本机中所有IP的端口。

本机IP

本机IP通常仅指在同一个局域网内,能同时被外部设备访问和本机访问的那些IP地址(可能不止一个)。像127.0.0.1这种一般是不被当作本机IP的。本机IP是与具体的网络接口绑定的,比如以太网卡、无线网卡或者PPP/PPPoE拨号网络的虚拟网卡,想要正常工作都要绑定一个地址,否则其他设备就不知道如何访问它。

小例子剧场(帮助理解本机IP、127.0.0.1和0.0.0.0)

现在有两台pc在同一个局域网内,分别为pc1与pc2,pc1上有一个网卡,IP地址为192.168.10.128

  • pc1中sever监听127.0.0.1,则pc1中的client可以连上127.0.0.1192.168.10.128连不上;而pc2中client都连不上。
  • pc1中sever监听192.168.10.128,则pc1中的client可以连上192.168.10.128127.0.0.1连不上;而pc2中client能连上192.168.10.128
  • pc1中sever监听0.0.0.0,则pc1中的client可以连上127.0.0.1192.168.10.128,pc2中的client能连上192.168.10.128

一般情况下我们在本地建立的MySQL数据库都是默认域名地址localhost(127.0.0.1)端口号是:3306

image-20250429191704197

上图的两个数据库其实是一个因为他们的IP地址都是一样的。

先建立连接到我本地的数据库lab2

image-20250429192035385

pymysql

import pymysql

def create_mysql_connection(db_name, host, user, password, port):
connection = pymysql.connect(
host=host,
user=user,
password=password,
db=db_name,
port=port,
charset='utf8mb4', # 设置字符集为utf8mb4,以支持更多字符
cursorclass=pymysql.cursors.DictCursor # 返回字典形式的结果
)
return connection

# 使用示例
db_name = 'lab2'
host = 'localhost'
user = 'root'
password = '123' # 替换为你的数据库密码
port = 3306 # MySQL默认端口是3306,如果你的端口不是这个,需要修改

# 创建连接
try:
dbc = create_mysql_connection(db_name, host, user, password, port)
print("MySQL database connection was successful")
except Exception as e:
print(f"The error '{e}' occurred")

# 关闭连接
# try:
# connection.close()
# print("MySQL connection is closed")
# except NameError:
# print("MySQL connection was not established")

连接成功后会返回

MySQL database connection was successful

获取MySQL版本号测试是否连接成功

# 获取MySQL版本号测试是否连接成功
cursor = dbc.cursor()
cursor.execute("select version()")
data = cursor.fetchone()
print(data)

成功后返回我的MySQL版本号:{'version()': '8.0.41'}

连接成功后先用SQL在lab2中创建一张test_table表用于接下来的操作

use lab2;
create table test_table(
_id int PRIMARY KEY AUTO_INCREMENT,
articleid varchar(500),
content varchar(500),
userid varchar(500),
nickname varchar(500),
likenum int,
stare int
)

下图中我已向其中添加了一些数据了,请忽略

image-20250430201023780

之后我们就可以写插入函数了:

def insert_data_mysql(connection, data):
#注意,在pymysql不管原数据库中的列值类型是字符串varchar还是int 占位符一律用 %s pymysql会自己转换数据类型(真棒!^_^)
sql = "INSERT INTO test_table (_id, articleid, content, userid, nickname, likenum, stare) VALUES (%s, %s, %s, %s, %s, %s, %s )"
connection.cursor().executemany(sql, data)
connection.commit()

然后我们自己造些测试数据:

data_to_insert_before_mysql = [[1, '1', '测试一下!', '11', '相忘于江湖', "64", 1]]

再写个循环扩大数据规模,多少条好呢**(´・д・)?* 1000条吧:

import copy
def create_data_1000_mysql(data_to_insert):
for i in range(0,999):
# 这里一定要注意一定得用深拷贝
data_to_insert_copy = copy.deepcopy(data_to_insert[i])
data_to_insert_copy[0] = data_to_insert[i][0] + 1
# 这里data_to_insert_copy还是一维列表所以记得套个[]
data_to_insert = data_to_insert + [data_to_insert_copy]
return data_to_insert
data_to_insert_after_mysql = create_data_1000_mysql(data_to_insert_before_mysql)
print(data_to_insert_after_mysql[-1])

料理完Mysql了接下来处理MongoDB,思路都是一样的只是语法稍微不同

连接:

from pymongo import MongoClient

def create_mongo_connection(uri):
client = MongoClient(uri)
return client

# 使用示例
mongo_client = create_mongo_connection('mongodb://localhost:27017/') #这里是默认的端口
mongo_db = mongo_client['test_db']
mongo_collection = mongo_db['test_collection']

测试是否连接成功:

# 列出当前正在使用的数据库以确保连接成功
def list_databases(client):
databases = client.list_database_names()
print("Databases in MongoDB instance:")
for db in databases:
print(db)

# 调用函数
list_databases(mongo_client)

输出结果:

image-20250430212608684

连接ok

写MongoDB的插入函数:

def insert_data_mongo(collection, data):
try:
collection.insert_many(data)
print("Data inserted successfully into MongoDB.")
except Exception as e:
print(f"An error occurred: {e}")

造数据:

data_to_insert_before_mongo = [
{"_id": 31000, "articleid": "1", "content": "测测", "userid": "11", "nickname": "相忘于江湖", "likenum": 64, "state": 1}
# 可以在这里添加更多数据
]

来1000条:

(和上述Mysql造1000条的逻辑是一样的,只不过在pymongo库中数据是用字典表示的)

def create_data_1000_mongo(data_to_insert):
for i in range(0,999):
data_to_insert_copy = copy.deepcopy(data_to_insert[i])
data_to_insert_copy["_id"] = data_to_insert[i]["_id"] + 1
data_to_insert = data_to_insert + [data_to_insert_copy]
return data_to_insert
data_to_insert_after_mongo = create_data_1000_mongo(data_to_insert_before_mongo)
print(data_to_insert_after_mongo[-1])

再简单测试一下二者插入上述相同数据所用时间的差异:

#插入1000条数据的性能测试模块
import time
start_time_sql = time.time()
insert_data_mysql(dbc, data_to_insert_after_mysql)
end_time_sql = time.time()
print(f"MySQL Insert 1000 pieces of data: {end_time_sql - start_time_sql} seconds")
start_time_mongo = time.time()
insert_data_mongo(mongo_collection, data_to_insert_after_mongo)
end_time_mongo = time.time()
print(f"MongoDB Insert 1000 pieces of data: {end_time_mongo - start_time_mongo} seconds")