目录
- 一、数据库事务机制
- 1.1 undo和redo日志
- 1.2 开启事务、提交事务、回滚事务
- 1.3 事务的ACID属性
- 1.4 事务的并发性
- 1.4.1 业务案例1:抢车票
- 1.4.2 业务案例2:转账
- 1.4.3 业务案例3 电商涨价
- 1.4.4 事务的序列化
- 二、数据导出与导入
- 2.1 SQL文件的导出与导入
- 2.2 TXT文档的导入与导出
- 三、综合案列:新闻管理系统数据库设计(表结构)
- 3.1 功能分析
- 3.2 数据表字段分析
- 3.3 密码的加解密
- 3.4 数据表的实现
一、数据库事务机制
事务机制: 避免写入直接操作数据文件,如果数据的写入直接操作数据 文件是非常危险的事情。例如:给员工涨工资,如果UPDATE语句执行过程中,系统重启了,那么就分不清哪个已经修改了,哪个还没修改。
- RDBMS = SQL语句 + 事务(ACID)
- 事务是一个或者多个SQL语句组成的整体,要么全部执行成功,要么全都执行失败。
1.1 undo和redo日志
利用日志来实现间接写入: MySQL共有5种日志文件,其中只有redo日志和undo日志与事务有关
1.2 开启事务、提交事务、回滚事务
管理事务:
- 默认情况下,MySQL执行每条SQL语句都会自动开启和提交事务
- 为了让多条SQL语句纳入到一个事务之下,可以手动管理事务
# 开启事务
START TRANSACTION;
SQL语句
[COMMIT | ROLLBACK];
# COMMOT将操纵持久化到数据文件,提交事务;ROLLBACK事务回滚
例子:
# 开启事务
START TRANSACTION;
DELETE FROM t_emp;
DELETE FROM t_dept;
SELECT * FROM t_emp;
SELECT * FROM t_dept;
此时查询到的t_emp
和t_dept
都是空的,但是现在SELECT查询实际上是到redo日志文件
中查询的。此时的表中的数据仍然存在,只要不提交事务,就不会和数据文件做同步。
# 提交事务,就会同步数据文件
# 将结果提交
COMMIT;
# 回滚,所有修改记录一起回滚。MySQL将日志文件打上标记
ROLLBACK;
1.3 事务的ACID属性
-
原子性
一个事务中的所有操作要么全部完成,要么全部失败。事务执行后,不允许停留在中间某个状态。
-
一致性
不管在任何给定的时间、并发事务有多少,事务必须保持运行结果的一致性。要求事务在并发的情况下不会数据的歧义。阻止事务之间相互读取临时数据。
比如:A、B、C、D四人相互转账总和不变
-
隔离性
隔离性要求事务不受其他并发事务的影响,如同在给定时间内,该事务是数据库唯一运行的事务。
undo和redo日志中数据会被标记属于哪个事务
默认情况下A事务,只能看到日志中该事务的相关数据。
-
持久性
事务一旦提交,结果便是永久性的。即便发生宕机,仍然可以依靠事务日志完成数据的持久化。
1.4 事务的并发性
事务并发执行的情况下,由于事务的隔离性会给某些业务带来问题,因此要修改事务的隔离级别
事务的四个隔离级别
序号 | 隔离级别 | 功能 |
---|---|---|
1 | read uncommitted | 读取未提交数据 |
2 | read committed | 读取已提交数据 |
3 | repeatable read | 重复读取 |
4 | serializable | 序列化 |
1.4.1 业务案例1:抢车票
A事务先购买G8047车次1车厢1A坐席,还未提交订单。此时B事务应该能够读取到A事务的状态,即读取未提交数据,才不会发生冲突和A事务争抢该坐席。
修改事务的隔离级别
READ UNCOMMITTED 代表可以读取其他事务未提交的数据
不设置隔离级别,默认读不到其他事务的临时数据。如下:
修改隔离级别,如下:
1.4.2 业务案例2:转账
只能读取其他业务提交以后的数据
A事务开启,还未操作。B事务将余额改为4900元,A事务转账在余额上加1000即可5900元,如果AB事务都COMMIT没问题。但如果B事务是错误的消费,需要退回,B事务执行ROLLBACK, 如果允许A事务读取B事务的临时数据,那就是4900+1000=5900,少了100块就不对了。
READ COMMITED 代表只能读取其他事务提交的数据
用法同上
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
1.4.3 业务案例3 电商涨价
A事务购买某商品,还未支付,B事务执行该商品涨价,所以客户下单购买应该是涨价之前的价格购买。因此当前的事务就不能受其他的事务影响。
事务执行之前会把数据拷贝到undo日志中,当repeatable read隔离级别只去读取undo日志中属于自己的那部分数据,因此不会收到其他事务的影响
REPEATABLE READ 代表事务在执行中反复读取数据,得到的结果是一致的,不会收到其他事务的影响。(默认的隔离级别)
用法同上
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
注意: 第一个session在commit之前,第二个session要启动事务设置,隔离并去查询才会将查询数据加载undo日志中,然后第一个session执行commit后在去第二个session查询数据,数据不受第一session的影响。
1.4.4 事务的序列化
由于事务并发执行所带来的各种问题,前三种隔离级别只适用在某些业务场景中,但是序列化的隔离性,让事务逐一执行,就不会产生上述问题。这种隔离级别使数据库的并发性极具下降,一般不用。
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
二、数据导出与导入
数据导出与备份的区别:
数据导出,导出的纯粹是业务数据
数据备份,备份的是数据文件、日志文件、索引文件等等
备份第一次是全量备份,有了全量备份后以后的备份就是增量备份。
2.1 SQL文件的导出与导入
导出SQL文件:
导出sql文件,文件包含了表结构和业务数据
命令行方式:
# no-data可写可不写,表示是否要导出数据文件
# 逻辑库就是要导出的数据库,敲回车后然后输入密码,OK
mysqldump -uroot -p [no-data] 逻辑库 > 导出路径
图形化界面: 双击选中逻辑库—>右键存储SQL文件…
导入SQL文件:
命令行方式:
# 先进入要导入的逻辑库
USE demo;
# 然后导入,source后加路径和文件名
SOURCE 文件路径;
2.2 TXT文档的导入与导出
导出只有纯粹的文档,而不是SQL语句
等再次导入的时候,由于文本文档无SQL语句,MySQL执行导入的时候会跳过词法分析和语法优化,直接把文本文档里的数据写入到MySQL的数据文件中,导入的速度非常快,因此数据量大的时候很适合。
导出文本文件:
导出文本文档,把文本文档拿到其他的MySQL数据库上因不知道表结构没法还原,因此先备份表结构
图形化界面:
- 备份表结构: 选中某个表—>右键转储SQL文件—>仅结构
- 导出该表的数据: 选中该表—>右键导出向导—>.txt文本文件—> 选择要导出的数据表 …
导入文本文件:
图形化界面:
-
选中—>运行SQL文件—> 导入表结构(找到路径)
-
选中表—> 导入向导—> 选中.txt文档…跟着提示做。
注意点: 第一个数据行 , 将txt文档的数据与表结构的映射关系选好
三、综合案列:新闻管理系统数据库设计(表结构)
3.1 功能分析
主要功能:
选择你要执行的操作
- 新闻列表
- 新建新闻
- 编辑新闻
- 退出
用例图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PCKcrFJ3-1690034255061)(C:\Users\zhao\AppData\Roaming\Typora\typora-user-images\1690018319575.png)]
3.2 数据表字段分析
新闻的属性:
数据库的ER图:
🔑:主键
◇: 唯一性约束
3.3 密码的加解密
数据加密:
密码不能存储为明文,要进行加密
对称加密: 加密解密都是一个,加密速度快,可以短时间对大量数据加密,但是加密强度不如非对称加密,多用于文件加密。DES加密已被淘汰
非对称加密: 公钥和私钥,两把密钥都可以用来加密和解密,一个加密,另一个解密。加密强度高,加密的速度慢,主要用于互联网和电信领域。
MySQL数据库提供了AES加密和解密的函数,所以数据的加密解密很容易实现
AES加密解密用法:
AES_ENCRYPT(原始数据, 密钥字符串)
例子:
# HEX()将二进制转换为十六进制
SELECT HEX(AES_ENCRYPT("你好世界", "ABC123456"));
# 输出结果:E85A104B6142A7375E53C0545CAD48EE
AES解密函数用法:
AES_DECRYPT(加密结果, 密钥字符串)
例子:
# UNHEX()是将十六进制转换为二进制
SELECT AES_DECRYPT(UNHEX("E85A104B6142A7375E53C0545CAD48EE"),"ABC123456");
3.4 数据表的实现
类型表的创建:
CREATE DATABASE vaga;
USE vaga;
CREATE TABLE t_type(
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
type varchar(20) NOT NULL UNIQUE
);
INSERT INTO t_type(type) VALUES("要闻"), ("体育"), ("科技"), ("娱乐"), ("历史");
角色表的创建:
CREATE TABLE t_role(
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
role VARCHAR(20) NOT NULL UNIQUE
);
INSERT INTO t_role(role) VALUES("管理员"), ("新闻编辑");
用户表的创建:
CREATE TABLE t_user(
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(20) NOT NULL UNIQUE,
password VARCHAR(500) NOT NULL,
email VARCHAR(100) NOT NULL,
role_id INT UNSIGNED NOT NULL,
INDEX (username)
);
插入两条数据:
INSERT INTO t_user(username, password, email, role_id)
VALUES("admin", HEX(AES_ENCRYPT("123456","HelloWorld")), "admin@163.com", 1);
INSERT INTO t_user(username, password, email, role_id)
VALUES("scott", HEX(AES_ENCRYPT("123456","HelloWorld")), "scott@163.com", 2);
新闻表的创建:
CREATE TABLE t_news(
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(40) NOT NULL,
editor_id INT UNSIGNED NOT NULL,
type_id INT UNSIGNED NOT NULL,
content_id CHAR(12) NOT NULL,
is_top TINYINT UNSIGNED NOT NULL,
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
state ENUM("草稿", "待审批", "已审批", "隐藏") NOT NULL,
INDEX(editor_id),
INDEX(type_id),
INDEX(state),
INDEX(create_time),
INDEX(is_top)
);
新闻内容用MongoDB存,MongoDB用来存储大量低价值数据,速度快效率高
MongoDB中主键都是12个字符的字符串