操作系统中数据存放的载体是文件,Windows、Linux和MacOS都是基于文件的操作系统
数据库管理系统是指一个能为用户提供信息服务的系统。它实现了有组织地、动态地存储大量相关数据的功能,提供了数据处理和信息资源共享的便利手段。
关系型数据库是指使用了关系模型的数据库系统。
关系模型中,数据是分类存放的,数据之间可以有联系。
关系型数据库可以有效组织和管理大量复杂的数据,所以关系型数据库才是最重要的数据库产品。
1976年IBM的System R团队在出版的论文中阐述了关系模型,1979年Oracle公司推出了首个关系型数据库成品。
NoSQL数据库指的是数据分类存放,但是数据之间没有关联关系的数据库系统。
是关系型数据库的补充,他们之间不是竞争关系。
比如秒杀库存的场景,100元的商品只卖10元,但是只有20件库存,关系型数据库都是多线程的,所以很容易出现超卖的问题,而比如有一种数据库Redis就是单线程的非关系型数据库可以解决这个问题。
还有关系型数据库存放数据之前需要先建表,保存约束条件等等,在高速写入的时候需要校验这些条件速度会降低,如果是重要数据还好,但要保存海量低价值的数据,就是对资源的极大浪费。比如朋友圈的信息跟银行转账记录相比,这样的数据没有必要保存到MySQL这样的关系型数据库里面,保存到NoSQL数据库里面就是最适合的了,NoSQL没有那么多表结构,数据读写也没有那么多校验,应用场景比如登录信息,网站的通知消息等很适合。
新闻内容都很长,MySQL的字符串类型 不适合保存太长的内容,所以新闻就应该保存到MongoDB数据库里面。
电商抢购促销的时候,商品信息数据从硬盘加载会比较慢,因此为了让消费者有更良好的用户体验,可以把商品强购信息保存到Redis内存里面。
微博上的热点信息,同样保存到Redis内存里面。
MySQL是应用最广泛,普及度最高的开源关系型数据库
MySQL由瑞典MySQL AB 公司开发,2008年MySQL AB被SUN收购,2009年SUN被Oracle收购,目前属于Oracle旗下产品
分为企业版和免费版,企业版的性能要比免费版好一些,而且还多了图形监控界面等等,本次学习的是免费版的MySQL,因为只有免费版的MySQL才具有大规模集群的意义,BAT大规模企业也都是用的免费版MySQL。
MySQL发展
1996年MySQL 1.0版本诞生,但是仅限于内部使用
1999年MySQL AB公司在瑞典成立
2000年MySQL 4.0 发布
2003年MySQL 5.0发布 跨时代的新版本,支持了事务机制,可以保证数据的完整性和一致性
**MariaDB:**血统最纯正的是Oracle甲骨文官方的Mysql数据库。
**Percona Server:**在数据库上性能最好的是Percona公司的Percona Server数据库,Percona是一家数据库业务咨询公司,它每年都会根据甲骨文发布的MySQL做定制优化,调优MySQL的性能然后进行二次发布,Rercona Server数据库只能安装在Linux系统上,Percona Server数据库对服务器做的很多优化,安装在个人PC里面性能不能很好的发挥。
**MariaDB:**目前活跃度比较高,因为MySQL数据库被Oracle收购,而且Oracle也尝试修改了MySQL数据库开源许可,所以很多大企业非常担心MySQL未来会继续开源,包括MySQL的发明人也是这么想的,于是他创立了MariaDB基金会,在MySQl5.5版本的基础上开发出了MariaDB数据库,业界对这款数据库的开源精神非常赞赏,但是毕竟剑走偏锋,MariaDB已经跟血统最纯正的Oracle发布的MySQL出现一些不兼容了。
下载链接:https://www.mysql.com/
这里建议一定要去下载安装版的MySQL,因为虽然解压缩绿色版可以直接用,但是如果存在电脑系统误删丢失一些dll文件就可能出现无法使用的问题。
https://dev.mysql.com/downloads/mysql/
下载好之后进入安装环节:
打开下载好的软件安装,默认选中的是开发版的MySQL,除了安装MySQL之外,还安装了一些MySQL的开发工具,还有自带的图形界面,这些工具一般用不上并且不太好用,不如第三方客户端用起来顺手,所以这里我只安装MySQL数据库,选择Server only。
Next提示需要安装一个c++程序包,点击Execute安装,这里要联网状态才能安装这个包
弹出安装c++包的提示,点击安装
等待程序包安装好后Next,选择执行Execute
Next进入配置环节,首先是MySQL的集群设置,因为我现在是单机不涉及集群,所以继续Next
MySQL的端口号默认3306,如果你的电脑上安装过MySQL或者被占用,要改成其他的。
因为MySQL引入了新的密码加密机制,所以默认选择的第一个,但是这里建议选下面的,否则使用最新的加密机制,如果使用python,Java等老驱动的连接MySQL8.0没有新的加密机制,就会无法连接。
MySQL自带的管理员账户是root,这里设置密码
MySQL要给Windows系统建立一个服务MySQL80,下面Start the MySQL Server at System Startup勾选是随着系统启动而启动MySQL。
点击Execute执行这些配置
到此完成安装。
打开MySQL的目录可以看到,bin目录里面是管理MySQL数据库的指令,这些指令在Windows终端是找不到的,只有进到这个目录下才能找到,为了让这些指令在Windows全局都生效,下面配置一下环境变量。
复制bin目录,在Path变量中新建,粘贴目录,确定即可完成配置
打开一个命令行登录测试一下,mysql -uroot -p
,-u后面是账号,-p代表一会输入密码
随便输一段指令测试一下,输入show databases;
打印mysql数据目录存放数据文件的文件夹
之前MySQL数据库默认自带的管理员root账户权限是最高的,有时只有数据库管理员才会用root账户登录MySQL,对于开发人员为其创建权限较低的用户,比如只能进行增删改查的操作,不允许销毁数据表这样的敏感操作。
可以14天使用,也可以安装破解版
新建连接,可以看到自带的4个逻辑空间
MySQL自带的4个逻辑空间非常重要,建议不要随便修改删除。
点击用户 - 新建用户
主机填写ip地址,%号代表可以使用任何主机登录dec账号
密码加密插件可以不选使用MySQL自带的
点击保存即可创建成功
服务器权限中勾选是针对MySQL数据库全局的权限,这个权限比较大,我们可以新建一个数据库来分配权限
点击新建查询编写创建数据库语句;新建一个test数据库
create database test;
分配自定义的权限,只给dev用户分配test数据库的增删改查权限,保存
这里还有一个坑,刚刚设置完之后,连接的时候提示:select command denied to user ...
,information_schema是存放一些基本信息的,dev用户连接时应该是要查询这个里面的内容,所以给予select权限即可。(教程中没有给这个权限却通过了,我把这个权限给予再删除也通过了,可能是版本问题?)
新建连接使用dev用户登录测试一下
MySQL数据文件存储在data目录(ProgramData是隐藏目录),my.ini是数据库的配置信息
进入data,可以看到test刚刚创建的数据空间
其他用户密码忘记可以登录root账户,给其他账户重置密码
创建一个txt文件,定义修改密码的SQL语句localhost是本地登录或可以设置远程登录(%允许本地和远程登录)
ALERT USER 'root@localhost' IDENTIFIED BY '123456';
在Windows图标右键,打开Windows PowerShell(管理员)
首先停止MySQL服务,输入:
net stop mysql80
然后启动数据库并修改密码
mysqld --defaults-file"mysql配置文件路径\my.ini" --init-file="刚刚建的txt文件路径.txt" --console
按下Control+C可以关闭MySQL服务
再启动一个Windows PowerShell(管理员),输入net start mysql80
即可启动MySQl服务
在my.ini文件中,我们可以设置各种MySQL的配置,例如字符集、端口号、目录地址等等,要想修改使my.ini配置服务生效可以重启MySQL服务
客户端配置信息:
[client] 图形界面设置
[mysql] 命令行客户端设置
数据库配置信息:
[mysqld]
打开my.ini查看信息
# 在连接时没指明端口默认使用3306 [client] port=3306 # mysql执行错误主板不发出蜂鸣器报警声 [mysql] no-beep [mysqld] port=3306 #端口号 datadir=C:/ProgramData/MySQL/MySQL Server 8.0\Data #数据目录 default_authentication_plugin=mysql_native_password #密码认证插件 default-storage-engine=INNODB #默认存储引擎 sql-mode="STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION" #开启严格模式(比如不开启对数据类型检查是否严格,比如向字符串类型存数字,会自动转换) log-output=FILE #用文件记录日志 general-log=0 #关闭日志输出 general_log_file="LAPTOP-9SVSSH7T.log" #日志文件名称 slow-query-log=1 #开启慢查询日志 slow_query_log_file="LAPTOP-9SVSSH7T-slow.log" #慢查询日志文件名称 long_query_time=10 #大于多少秒执行的SQL被记录在慢查询日志 log-error="LAPTOP-9SVSSH7T.err" #错误日志名称 log-bin="LAPTOP-9SVSSH7T-bin" server-id=1 #数据库ID(当前是单价版不需要使用,在使用集群的时候使用这个ID值做区别) lower_case_table_names=1 #把表面转换为小写 secure-file-priv="C:/ProgramData/MySQL/MySQL Server 8.0/Uploads" #导入导出数据的目录地址 max_connections=151 #最大连接数 table_open_cache=2000 tmp_table_size=100M #缓存大小 thread_cache_size=10 #线程数量 myisam_max_sort_file_size=100G myisam_sort_buffer_size=191M key_buffer_size=8M read_buffer_size=64K read_rnd_buffer_size=256K innodb_flush_log_at_trx_commit=1 innodb_log_buffer_size=1M innodb_buffer_pool_size=8M innodb_log_file_size=48M innodb_thread_concurrency=33 innodb_autoextend_increment=64 innodb_buffer_pool_instances=8 innodb_concurrency_tickets=5000 innodb_old_blocks_time=1000 innodb_open_files=300 innodb_stats_on_metadata=0 innodb_file_per_table=1 innodb_checksum_algorithm=0 back_log=80 flush_time=0 join_buffer_size=256K max_allowed_packet=4M max_connect_errors=100 open_files_limit=4161 sort_buffer_size=256K table_definition_cache=1400 binlog_row_event_max_size=8K sync_master_info=10000 sync_relay_log=10000 sync_relay_log_info=10000 loose_mysqlx_port=33060
DML数据操纵语言:添加、修改、删除、查询
DCL数据控制语言:用户、权限、事务
DDL数据定义语言:逻辑库、数据包、视图、索引
SQL语句注意事项
SQL语句不区分大小写,但是字符串区分大小写
SQL语句必须以分号结尾
SQL语句中空白和换行没有现在,但是不能破坏语法
SQL语句的注释
# 单行注释 /*多行注释*/
创建、查看、删除
mysql> create database 逻辑库名称; mysql> show databases; mysql> drop database 逻辑库名称;
create table 数据表( 列名1 数据类型 [约束] [comment 注释], 列名2 数据类型 [约束] [comment 注释], ... )[comment=注释];
示例:
USE test; #使用text逻辑库 create table student( id int unsigned primary key, name varchar(20) not null, sex char(1) not null, birthday date not null, tel char(11) not null, remark varchar(200) );
可以看到tes目录中出现了刚刚建立的数据表student.ibd文件
show tables; #查看逻辑空间里数据表名 desc student; #查看student数据表的具体情况 show create table student; #查看student表创建时的sql语句 drop table student; #删除数据表
类型 | 大小 | 说明 |
---|---|---|
TINYINT | 1字节 | 小整数 |
SMALLINT | 2字节 | 普通整数 |
MEDIUMINT | 3字节 | 普通整数 |
INT | 4字节 | 较大整数 |
BIGINT | 8字节 | 大整数 |
FLOAT | 4字节 | 单精度浮点数 |
DOUBLE | 8字节 | 双精度浮点数 |
DECIMAL | — | DECIMAL(10,2) |
可以定义TINYINT加UNSIGNED定义为无符号,范围就是0-255
单精度和双精度保存数据是有误差的,保存一些不太精确的数据可以,但是要保存比如钱要用DECIMAL类型,因为10进制浮点数转2进制是会丢数据的,而DECIMAL是使用字符串的方式保存数据,不涉及数字转换;DECIMAL(10,2)表示精确到小数点后2为,整数位加小数位共10位。
不精确的浮点数
十进制的浮点数无法在计算机中用二进制精确表达;比如要用二进制小数表示十进制的0.2,=1/8+1/16+1/128+…只能无限接近,不能完全相等。
案例:
create table temp( id int UNSIGNED PRIMARY KEY, num FLOAT(20,10) ); INSERT INTO temp VALUES(1,0.2); SELECT * FROM temp;
查询得到结果不是0.2而变成了0.2000000030
id | num |
---|---|
1 | 0.2000000030 |
类型 | 大小 | 说明 |
---|---|---|
CHAR | 1-255字符 | 固定长度字符 |
VARCHAR | 1-65535 | 不固定长度字符串 |
TEXT | 1-65535 | 不确定长度字符串 |
MEDIUMTEXT | 1-1千6百万字符 | 不确定长度字符串 |
LONGTEXT | 1-42亿字符 | 不确定长度字符串 |
类型 | 大小 | 说明 |
---|---|---|
DATE | 3字节 | 日期 |
TIME | 3字节 | 时间 |
YEAR | 1字节 | 年份 |
DATETIME | 8字节 | 日期时间 |
TIMESTAMP | 4字节 | 时间戳 |
ALERT TABLE 表名称 ADD 列1 数据类型 [约束] [COMMENT 注释], ADD 列2 数据类型 [约束] [COMMENT 注释], ...;
ALTER TABLE student ADD address VARCHAR(200) NOT NULL, ADD home_tel CHAR(11) NOT NULL;
ALERT TABLE 表名称 MODIFY 列1 数据类型 [约束] [COMMENT 注释], MODIFY 列1 数据类型 [约束] [COMMENT 注释], ...;
ALTER TABLE student MODIFY home_tel VARCHAR(11) NOT NULL;
ALERT TABLE 表名称 CHANGE 列1 新列名 数据类型 [约束] [COMMENT 注释], CHANGE 列2 新列名 数据类型 [约束] [COMMENT 注释], ...;
ALTER TABLE student CHANGE address home_address VARCHAR(200) NOT NULL;
ALTER TABLE student DROP 列1; DROP 列2; ...;
ALTER TABLE student DROP home_address, DROP home_tel;
数据库的范式
构造数据库必须遵循一定的规则,这种规则就是范式
目前关系数据库有6种范式,一般情况下,只满足第三范式即可
第一范式是数据库的基本要求,不满足这一点就不是关系数据库
数据表的每一列都是不可分割的基本数据项,同一列中不能有多个值,也不能存在重复的属性。
不符合第一范式:
学号 | 姓名 | 班级 |
---|---|---|
1000 | 张三 | 高三年级1班 |
符合第一范式:
学号 | 姓名 | 年级 | 班级 |
---|---|---|---|
1000 | 张三 | 高三 | 1班 |
数据表中的每条记录必须是唯一的。为了实现区分,通常为表加上一列来存储唯一标识,这个唯一属性列被称作主键列。
不存在部分函数依赖
每列都与主键有直接关系,不存在传递依赖。
不符合第三范式:
爸爸 | 儿子 | 女儿 | 女儿的玩具 | 女儿的衣服 |
---|---|---|---|---|
张三 | 张一 | 张二 | 皮卡丘 | 校服 |
符合第三范式:
爸爸 | 儿子 | 女儿 |
---|---|---|
张三 | 张一 | 张二 |
女儿 | 女儿的玩具 | 女儿的衣服 |
---|---|---|
张二 | 皮卡丘 | 校服 |
符号第三范式的数据表查找和提取数据速度快
依照第三范式,数据可以拆分保存到不同的数据表,彼此保持关联
约束名称 | 关键字 | 描述 |
---|---|---|
主键约束 | PRIMARY KEY | 字段值唯一,且不能为NULL |
非空约束 | NOT NULL | 字段值不能为NULL |
唯一约束 | UNIQUE | 字段值唯一,且可以为NULL |
外键约束 | FOREIGN KEY | 保持关联数据的逻辑性 |
CREATE TABLE t_teacher( id INT PRIMARY KEY AUTO_INCREMENT, ... );
非空约束要求字段值不能为NULL值
NULL值是没有值,而不是""空字符串
CREATE TABLE t_teacher( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20) NOT NULL, married BOOLEAN NOT NULL DEFAULT FALSE );
DEFAULT FALSE指如果没填数据默认为FALSE
MySQL中是BOOLEAN类型, 当创建BOOLEAN类型后,MySQL会把BOOLEAN映射成TINYINT的0和1。
唯一约束要求字段值如果不为NULL,那么在全表必须唯一
CREATE TABLE t_teacher( ... tel CHAR(11) NOT NULL UNIQUE );
外键约束用来保证关联数据的逻辑关系
外键约束的定义是写在子表上的
父表:
CREATE TABLE t_dept( deptno INT UNSIGNED PRIMARY KEY, dname VARCHAR(20) NOT NULL UNIQUE, tel CHAR(4) UNIQUE );
子表:
CREATE TABLE t_emp( empno INT UNSIGNED PRIMARY KEY, ename VARCHAR(20) NOT NULL, sex ENUM("男","女") NOT NULL, deptno INT UNSIGNED NOT NULL, hiredate DATE NOT NULL, FOREIGN KEY (deptno) REFERENCES t_dept(deptno) );
如果形成外键闭环,我们将无法删除任何一张表的记录
因此在真实的数据项目中,一般不推荐使用外键约束
数据库后台通过维护二叉树来管理索引机制
在创建数据表的时候创建索引,如果不规定索引名称会使用字段名创建
CREATE TABLE 表名称( ..., index [索引名称] (字段), ... );
# 添加索引的2中方式 CREATE INDEX 索引名称 ON 表名 (字段); ALERT TABLE 表名称 ADD INDEX [索引名] (字段); # 查看索引 SHOW INDEX FROM 表名; # 删除索引 DROP INDEX 索引名称 ON 表名;
数据库课程学过N遍满分结课不写了。。。
避免写入直接操作数据文件
如果数据的写入直接操作文件是非常危险的事情,在写入过程中如果停电或死机突然中断会产生严重的数据同步问题
利用日志来间接写入
MySQL总共有5种日志,其中只有redo日志和undo日志与事务有关
RDBMS = SQL语句 + 事务(ACID)
事务是一个或多个SQL语句组成的整体,要么全部执行成功,要么全部执行失败
事务案例:
把10部门种MANGER员工调往20部门,其他岗位员工调往30部门,然后删除10部门
默认情况下,MySQL执行每条SQL语句都会自动开启和提交事务
为了让多条SQL语句纳入到一个事务之下,可以手动管理事务
START TRANSACTION; SQL语句 [COMMIT|ROLLBACK];
原子性
一个事务种的所有操作要么全部完成,要么全部失败。事务执行后,不允许停留在中间某个状态。
一致性
不管在任何给定的时间、并发事务有多少,事务必须保证允许结果的一致性
隔离性
隔离性要求事务不受其他并发事务的影响,如同在给定的时间内,该事务是数据库唯一运行的事务
默认情况下A事务,只能看到日志中该事务的相关数据
持久性
事务一旦提交,结果便是永久性的。即便发生宕机,仍然可以依靠事务日志完成数据的持久化
隔离级别 | 功能 |
---|---|
read uncommitted | 读取未提交的数据 |
read committed | 读取已提交的数据 |
repeatable read | 重复读取 |
serializable | 序列化 |
可以读取其他事务未提交的数据
START SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
**适用场景:**买票
事务一:
START TRANSACTION; UPDATE t_emp SET sal=1;
事务二:
START SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; START SESSION; SELECT * FROM t_emp; COMMIT;
事务二读取到了事务一未提交的数据。
只能读取其他事务提交的数据
START SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
**适用场景:**银行转账
事务一:
START TRANSACTION; UPDATE t_emp SET sal=1; COMMIT; # 如果不提交事务二读取不到
事务二:
START SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; START SESSION; SELECT * FROM t_emp; COMMIT;
MySQL默认事务隔离级别,事务在执行中反复读取数据,得到的结果是一致的,不会受其他事务影响
START SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
**适用场景:**商品下单时涨价
事务一:
START TRANSACTION; UPDATE t_emp SET sal=1 COMMIT; # 如果不提交事务二读取不到
事务二:
START SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; START SESSION; SELECT * FROM t_emp; COMMIT;
由于事务并发执行带来的各种问题,前三种隔离级别只适用在某些业务场景中,但是序列化的隔离性,让事务逐一执行,就不会产生上述问题了。虽然序列化事务能避免业务场景的问题,但是随之而来数据库的并发性急剧下降,所以很少使用。
START SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
数据导出,导出的纯粹是业务数据
数据备份,备份的是数据文件、日志文件、索引文件等等
全量备份 -> 增量备份1 -> 增量备份2
分为导出SQL文件(少量数据)和文本文档(大量数据)
命令行方式:
mysqldump用来把数据导出成SQL文件,其中也包括了表结构,no-data只导出表结构
mysqldump -uroot -p [no-data] 逻辑库 > 路径
案例:
mysqldump -uroot -p test > D:/data/test.sql;
然后输入密码
在 D:/data出现导出的test.sql文件
图形界面方式:
source命令用于导入SQL文件,包括创建数据表,写入记录等
sql > USE test; sql > SOURCE sql文件路径;
案例:
要在数据库命令行下执行,首先登录数据库:
mysql -uroot -p
然后选择逻辑库和导入
USE test; SOURCE D:/data/test.sql;
命令行的方式比较复杂
图形就界面方式:
先保存表结构:
然后继续表右键 -> 导出向导 -> 文本文件 -> 选择t_emp表
要先导入表结构,运行sql文件之前导出的表结构
然后导入的t_emp右键 -> 导入向导 -> 文本文档