跳到主要内容

3 篇博文 含有标签「mysql」

查看所有标签

django+nginx+mysql 三容器部署

· 阅读需 4 分钟
Jason Lee
The owner of this blog site

前言

之前的部署直接采用默认的 sqlite3 作为数据库。因为 sqlite3 是文件式数据库,所以打造容器时,本地调试过程中的数据记录也被包含进去。另外,生产环境中,不可能使用 sqlite。因此,在之前的 django+nginx 的基础上,引入了 mysql 容器。

镜像设置

首先在根目录创建一个MySQL数据库,下面有 data.sql 和 Dockerfile。这里我们先单独启动一下 mydql 容器。这时候 mysql 容器里已经有 django 的数据库了(database)。这是因为 data.sql 已经提前创建好了数据库并设置为当前数据库:

CREATE DATABASE IF NOT EXISTS my_database;

USE my_database;

而 Dockerfile 的内容为:

FROM mysql:8

ENV MYSQL_ROOT_PASSWORD pass
COPY ./data.sql /docker-entrypoint-initdb.d/data.sql

最后一行使得 data.sql 在容器初始化时就被执行。这时候虽然有了数据库但是没有表格,需要去 django 项目下,执行python manage.py migrate来在库里面创建表格。运行docker exec -it <name> /bin/bash,进入容器 terminal,进入 mysql 命令行,show tables,可以得到:

16875289399621687528939092.png

说明,数据表格创建成功了。

django settings.py 变动

由于之前是默认的 sqlite3,配置非常简单,只需要指定数据库文件位置。在 django 的 settings.py 中,关于 mysql 数据库的设定为:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'my_database',
'HOST': 'database', #compose中mysql容器的服务名称
'PORT': '3306',
'USER': 'root',
'PASSWORD': 'pass',
'OPTIONS': {
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"
},
}
}

docker-compose

由于我们是全 docker 运行,因此也要实验一下将 django 项目打包成 docker 容器后,能否也能与 mysql 容器通信且成功创建表格。这次用 compose 实现。

version: "3.9"
services:
nginx:
build: ./wey-frontend/
restart: always
ports:
- "8000:80"
volumes:
- web_static:/var/www/mysite/assets/static
- web_media:/var/www/mysite/assets/media
depends_on:
- django

django:
build: ./wey_backend/
restart: always
expose:
- 8000
command: >
sh -c "python manage.py collectstatic --noinput
&& python manage.py migrate
&& uwsgi --ini uwsgi.ini"
volumes:
- web_static:/var/www/mysite/assets/static
- web_media:/var/www/mysite/assets/media
depends_on:
- database

database:
build: ./MySQL/
ports:
- '3306:3306'
# environment:
# MYSQL_DATABASE: 'appdb'
# MYSQL_PASSWORD: 'root'
# MYSQL_ROOT_PASSWORD: 'root'
# volumes:
# - 'db:/var/lib/mysql'
# # command: ['mysqld', '--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci']

volumes:
web_static:
web_media:

总结

用 mysql 作为数据库,更符合实际生产场景。由于一开始 mysql 容器内没有数据库,因此需要在 Dockerfile 中创建自定义数据库并且使用。django 的 settings.py 中也要作相应调整。docker-compose 中,需要在创建 django 容器后,执行python manage.py migrate,来迁移数据库(即在自定义数据库中创建表来供上线后数据放置)。

django关系字段

· 阅读需 4 分钟
Jason Lee
The owner of this blog site

前言

mysql 断断续续地学,一直对诸如外键的概念不甚清晰,今天做一个备忘。在这篇博文的基础上,加上了一些自己的理解。

建表

#_*_coding:utf-8_*_
from django.db import models

# Create your models here.

class Colors(models.Model):
colors=models.CharField(max_length=10) #蓝色
def __str__(self):
return self.colors

class Ball(models.Model):
color=models.OneToOneField("Colors") #与颜色表为一对一,颜色表为母表
description=models.CharField(max_length=10) #描述
def __str__(self):
return self.description

class Clothes(models.Model):
color=models.ForeignKey("Colors") #与颜色表为外键,颜色表为母表
description=models.CharField(max_length=10) #描述
def __str__(self):
return self.description

class Child(models.Model):
name=models.CharField(max_length=10) #姓名
favor=models.ManyToManyField('Colors') #与颜色表为多对多

一对一(models.OneToOneField)

子表从母表中选出一条数据一一对应,母表中选出来一条就少一条,子表不可以再选择母表中已被选择的那条数据。一般用于某张表的补充,比如用户基本信息是一张表,但并非每一个用户都需要有登录的权限,不需要记录用户名和密码,此时,合理的做法就是新建一张记录登录信息的表,与用户信息进行一对一的关联,可以方便的从子表查询母表信息或反向查询。

## 增加

color_obj=models.Colors.objects.create(colors="黑") #先在母表中创建颜色,并实例化给颜色表对象
models.Ball.objects.create(color=color_obj,description="黑球") #更新Ball表,color字段为颜色表对象,添加description字段

## 删除
models.Ball.objects.get(description="灰球").delete()

## 修改
color_obj=models.Colors.objects.get(colors="黑") #.get()等同于.filter().first()
color_obj.colors="灰"
color_obj.save()
models.Ball.objects.filter(description="黑球").update(color=color_obj,description="灰球")

## 查询
### 子表查询母表
models.Ball.objects.get(description="红球").color.colors

### 母表查询子表
models.Colors.objects.get(colors="红").ball.description

一对多(models.ForeignKey)

子表从母表中选出一条数据一一对应,但母表的这条数据还可以被其他子表数据选择。这里的一和多指的是自身的表的数据在对方表里出现的次数,一次为一,多次为多。比如每个员工归属于一个部门,那么就可以让员工表的部门字段与部门表进行一对多关联,可以查询到一个员工归属于哪个部门,也可反向查出某一部门有哪些员工。

## 查

color_obj=models.Colors.objects.get(colors="红")
color_obj.clothes_set.all()

models.Clothes.objects.filter(color__colors="红")

多对多(models.ManyToManyField)

比如有多个孩子,和多种颜色。每个孩子可以喜欢多种颜色,一种颜色可以被多个孩子喜欢,对于双向均是可以有多个选择。

## 查

#写法1:
child_obj=models.Child.objects.get(name="小明") #写法:子表对象.子表多对多字段.过滤条件(all()/filter())
print(child_obj.favor.all())
#写法2,反向从母表入手:
print(models.Colors.objects.filter(child__name="小明")) #母表对象.filter(子表表名小写__子表字段名="过滤条件")

mysql

· 阅读需 5 分钟

mysql的单表查询很简单,但是单表体积增大时,或者涉及到多表查询时就成了难点。本文主要对这些问题做一些记录。

mysql工作原理

mysql服务启动,监听3306端口。外界的客户端,如cmd,django框架,heidisql都视作客户端,用户名密码验证后可以连接到mysql服务。在操作系统中,数据库视作文件夹,每一张表都是一个特殊后缀的文件。 1668775623718.png

数据库的备份和恢复

备份的本质是创建一个sql文件。命令:

mysql -u -p -B db1 db2 > d:\\xxx.sql  -- 按照数据库来备份
mysql -u -p db1 table1 table2 > d:\\yyy.sql -- 按照表来备份
source d:\\xxx.sql -- 恢复

分页

在数据库规模较大的情况下,每次请求都是请求部分,这样就需要分页。

select * from table limit 每页记录数*(页序号-1, 每页记录数

多子句查询的先后顺序

select * from table
group by ..
hanving ..
order by ..
limit ..

自连接

将一张表当作两张表联合查询,需要给表取别名。

select * from table1 as A, table1 as B where ...

表自复制和去重

insert into table select * from table  -- 自复制,也可以用于制作表的备份
------
-- 表格去重流程:先创建新表,将去重的数据写入新表,然后删掉旧表,将新表改名
create table new like old; --创建字段和旧表一致的新表
insert into new select distinct * from old;
drop table old;
alter table new rename old;

外连接

按照下列模式:

select * from table1, table2 where ...

是在两表的笛卡尔积上进行筛选,这样,不符合筛选条件的数据不会列出。有时候我们需要列出不符合筛选条件的数据。外连接分为左右,以左外连接为例,左表的每一项都进入结果中,对于没有匹配上的字段,则赋为Null。语法:

select * from table1 left join table2 on ... -- 筛选条件是on

外键

为了对新插入的数据进行约束,引入了外键。假设,表A作为主表,也就是约束条件,表B作为从表,只能插入表A中主键存在的数据。一旦主表的主键被引用,就不能删除。

create table tab (
id int primary key,
class_id int,
--下面指定外键
foreign key (class_id) references my_class(id), -- my_class是主表。id必须是主键或者unique
)

check约束

注:mysql 8.0.16后开始全面支持check约束。

CREATE TABLE cc (
id INT,
sex VARCHAR(10) CHECK (sex IN('male', 'female'))
);

索引

索引是对一个字段建立的一个二叉树,提升查找速度。是一种空间换时间的策略。对于查找操作多于修改操作的数据库很有必要。

create index_name on table (ziduan)

事务

为了能将多个sql语句作为一个整体执行,事务提出,将增删改包裹起来。

start transaction; -- 开始事务,此时其他会话看不到事务过程中修改的数据结果
-- 执行一些操作 --
savepoint A; -- 设置保存点A
-- 执行一些操作 --
rollback to A; -- 回退到保存点A
rollback; -- 回退到事务开始时状态
commit -- 提交事务,删除所有保存点,此时修改后的数据向其他会话开放

隔离

为了确保事务获得数据的准确性,提出了隔离。默认隔离级别下,不同事务同时开启造成的问题有:

1668952763819.png

事务隔离级别和各级别会出现的问题:

1668952901628.png

select @@transaction_isolation; --查看当前事务隔离级别(mysql8.0+,低版本为select @@tx_isolation)