从零开始的MySQL教程——下
一、存储引擎
存储引擎是mysql中特有的术语,实际上存储引擎是一个表存储/组织数据的方式,不同的存储引擎,表存储数据的方式不同。
1.1 指定存储引擎
可以在建表的时候指定存储引擎和字符编码方式。
使用ENGINE来指定存储引擎。
使用CHARSET来指定字符编码方式。
mysql默认的存储引擎是: InnoDB,默认字符编码方式是: utf8
create table t_test(id int primary key;name varchar(255)
)engine = InnoDB default charset = ut8;
1.2 查看支持引擎
命令: show engines \G;
支持引擎情况跟数据库版本有关
命令: select version();
1.3 常用引擎
1.MyISAM存储引擎:
它的管理具有以下特征: 使用三个文件表示每张表
1. 格式文件 —— 存储表结构的定义(mytable.frm)
2. 数据文件 —— 存储表的数据内容(mytable.MYD)
3. 索引文件 —— 存储表上的索引(mytable.MYI)
MyISAM存储引擎特点: 内容被分开为三个文件,可被转换为压缩,只读表来节省空间。
MyISAM不支持事务,安全性低;
2.InnoDB存储引擎:
这是mysql默认的存储引擎,同时也是一个重量级的存储引擎。
InnoDB引擎支持事务,支持数据库崩溃后自动恢复机制。
InnoDB主要特点是特别安全。
他管理的表具有下列主要特征:
- 每个InnoDB表在数据库目录中以.frm格式文件表示
- InnoDB表空间tablespace被用于存储表的内容(表空间是一个逻辑名称,存储表内容和索引)
- 提供一组用来记录事务性活动的日志文件
- 用COMMIT(提交),SAVAPOINT及ROLLBACK(回滚)支持事务处理
- 提供全ACID兼容
- 在MySql服务器崩溃后提供自动恢复机制
- 多版本(MVCC)和行级锁定
- 支持外键及引用的完整性,包括级联删除和更新
InnoDB最大的特点就是支持事务: 以保证数据的安全,效率不是很高,并且也不能压缩,不能转换为只读,不能很好的节省存储空间。
3.MEMORY存储引擎:
使用MEMORY存储引擎的表,其数据存储在内存当中(一断电或其他意外方式导致程序退出就不存在了),且行的长度固定,这两个特点使MEMORY存储引擎非常快。
MEMORY存储引擎管理的表具有下列特征:
1. 在数据库目录内,每个表均以.frm格式的文件表示。2. 表数据及索引被存储在内存中(目的就是查询快)3. 表级锁机制。4. 不能包含TEXT或BLOB字段。
优点:查询效率是最高的,不需要和硬盘交互。
缺点:不安全,关机之后数据消失(数据和索引都存储在内存中)。
二、 事务
事务是一个完整的业务逻辑,是最小的工作单元,不能再细分,要么同时成功,要么同时失败。
事务怎么保证全部执行成功或者执行失败:
事务依赖于InnoDB存储引擎,提供一组用来记录事务性活动的日志文件,所有操作语句都会记录在日志当中,在事务的执行过程中,我们可以提交事务,也可以回滚事务。
提交事务: 清空事务性活动日志的问题件,将数据全部彻底持久化到数据库表中。(表示执行到这一步,没有发生意外情况,标志着事务的结束,并且是一种全部成功的结束)。
回滚事务: 将之前所有的操作全部撤销,并且清空事务性活动的日志文件。(回滚标志着事务结束,并且是全部失败的结束)。
提交事务和回滚事务:
- 提交事务:conmit;
- 回滚事务: rollback;(回滚到上一次的提交点)
- 事务: transaction
mysql默认情况下是支持自动提交事务的,每执行一条DML语句,则提交一次!
开始事务:
start transaction; -- 开启事务,关闭自动提交机制
...
...
...
#执行完所有语句后进行提交操作;
commit;
#或者执行回滚操作;
rollback;
事务包括四个特性:
A 原子性:
说明事务是最小的工作单元,不可再分;
C 一致性:
所有事务要求,在同一个事务当中,所有操作必须同时成功,或者同时失败,以保证数据的一致性;
I 隔离性:
A事务和B事务之间具有一定的间隔,不会互相影响。
例如:多线程并发访问同一张表
D 持久性:
事务最终结束的一个保障,事务提交,将没有保存到硬盘上的数据保存到硬盘上,不可逆操作。
隔离级别:(隔离性)
例如: A教室和B教室中间有一道墙,这道墙可以很厚,也可以很薄这就是事务的隔离级别;这道墙越厚,表示隔离级别越高;
事务和事务之间有四个隔离级别: 级别从低到高;
读未提交: read uncommitted、
事务A可以读取到事务B未提交的数据。
存在脏读现象(Dirty Read);
这种隔离级别一般都是理论上的,大多数的隔离级别都是二档起步!
读已提交: read committed
事务A只能读取到事务B提交时候的数据,这种隔离级别解决了脏读现象;
不可重复读取数据,再事务开启之后,第一次读到的数据是3条,当前事务还没有结束,可能第二次再读取的时候,读到的数据是4条,3不等于4成为不可重复读取。
这种隔离级别是比较真实的数据,每一次读到的数据是绝对真实的。
这是Oracle默认的隔离级别;
可重复读: repeatable read
事务A开启之后,不管是多久,每一次再事务A中读取到的数据都是一致的,即使事务B将数据已经修改,并且提交了,事务A读取到的数据还是没发生改变。
**可能会出现幻影读:**每一次读取到的数据都是幻象,不够真实。
MySql默认隔离级别是可重复读;
序列化/串行化: serializable
这是最高隔离级别,效率最低,这种隔离级别表示事务排队,不能并发,A事务开启时B事务要等待。类似于synchronized线程同步(事务同步),每一次读取到的数据都是真实的。
三、 索引
索引是各种数据库进行优化的重要手段,优化的时候优先考虑的因素就是索引,索引在数据库中分了很多类:
单一索引: 一个字段上添加索引
复合索引: 两个字段或者更多的字段上行添加索引
主键索引: 主键上添加索引
唯一性索引: 具有unique约束的字段上添加索引
注意:唯一性比较弱的字段上添加索引用处不大;
索引是在数据库的字段上添加的,是为了提高查询效率存在的一种机制。
一张表的一个字段可以添加一个索引,也可以多个字段联合起来添加索引。
索引相当于一本书的目录,是为了缩小扫描范围而存在的一种机制。
MySQL在查询方面主要有两种方式:
第一种: 全表扫描
第二种: 根据索引检索
注意:
在实际中,字典前面的目录也是排序的,按照abcdef…排序,只有排序了才有去检查找这一说(缩小扫描范围起使就是扫描某个区间)
在mysql数据库中索引也是需要排序的,并且这个索引的排序和TreeSet数据结构相同,TreeSet(TreeMap)底层是一个自平衡二叉树,在mysql当中索引是一个B-Tree数据结构。遵循左小右大原则存放,采用中序遍历方式遍历数据。
索引的实现原理:
假设有一张用户表: t_user
id(primary key) | name | 物理地址 |
---|---|---|
100 | zhangsan | 0X1111 |
120 | lisi | 0x2222 |
99 | wangwu | 0x8888 |
88 | zhaoliu | 0x9999 |
55 | lucy | 0x5555 |
101 | tom | 0x7777 |
130 | cherry | 0x6666 |
- 在任何数据库当中主键上都会自动添加索引对象,如果有unique约束的话,也会自动创建索引对象。
- 在任何数据库当中,任何一张表的任何一条记录在硬盘上都有一个硬盘的物理存储编号。
- 在mysql种索引是一个单独的对象,不同的存储引擎以不同的形式存在,在MyISAM存储引擎种,索引存储在一个.MYI文件中。在InnoDB存储引擎中索引存储在一个逻辑名叫做tablespace中。在MEMORY存储引擎当中索引被存储在内存当中,不管索引存储在哪里,索引在mysql当中都是一个树的形式存在。(自平衡二叉树: B-Tree)
例如:查找id为101的所有信息
select * from t_user where id = 101;
左小右大结构,mysql发现di字段上有索引对象,所以会通过索引对象idIndex进行查找,通过idIndex索引对象定位到:101(缩小扫描范围,快速定位)
通过101得出物理编号: 0x7777,此时SQL语句马上转换为:
select * from t_user where 物理地址 = 0x7777;
物理地址是寄存器的位置;
什么条件下,我们会考虑给字段添加索引?
- 在mysql中,设置了主键和unique的字段自动添加索引。
- 数据量庞大
- 该字段经常出现在where后面,以条件形式存在,也就是说这个字段总是被扫描
- 该字段很少的DML操作(delete,update,inser)操作,因为执行这些操作以后,索引需要重新排序。
建议不要随意添加索引,因为索引需要经常维护,太多的话反而降低系统的性能,建议通过主键查询,或通过unique约束的字段进行查询。
索引创建:
#创建:
create index 索引名 on 表名(字段名);
#给emp表的name字段添加索引,名称为emp_name;
create index emp_name on emp(name);
索引删除:
#删除:
drop index 索引名 on 表名;
#删除emp表中名为emp_name的索引;
dorp index emp_name on emp;
怎么查看一条sql语句是否使用索引查询:
在语句前面加关键字explain(解释说明);
explain select * from emp where name = 'king';
分析type(是否为ref)和查询行数;
索引有些情况下会失效:
- 使用模糊查询时以%开头;
select * from emp where name like '%L';
在这种情况下,即使name字段添加了索引,也不会走所以,原因是因为模糊匹配当中以"%"开头,任何字符都可以,没办法进行指定范围查找,尽量避免模糊查询的时候以%开头,这是一种优化策略;
使用or时,需要or两边的条件字段都要有索引,否则不会走索引,这也是尽量少用or的原因;
使用符合索引的时候,没有使用左侧的列查找,索引失效;
复合索引: 两个字段或者更多字段联合起来添加一个索引
-- 给job和sal字段添加联合索引 create index emp_job_sal_index on emp(job,sal); -- 使用左侧索引job,索引生效 explain select * from emp where job = 'manager'; -- 使用右侧索引sal,索引失效 explain select * from emp where sal = '1000';
在where中设置了索引的字段参与运算,索引会失效;
#不参与运算,索引生效 explain select * from emp where sal = '800'; #sal列参与运算,索引失效 explain select * from emp where sal+1 = '800';
在where中索引列使用了函数:
explain select * from emp where lower(name) = 'cherry';
四、 视图
view: 站在不同角度去看待同一份数据 **
创建视图对象:
create view 视图名 as DQL语句(查询);
#eg
create view emp_view as select * from emp;
删除视图对象:
dorp view 视图名;
#eg
drop view emp_view;
注意:只有DQL语句才能以view的形式创建
用试图做什么?
我们可以面向视图对象进行增删改查,对视图对象的操作,会导致原表受到相同操作的影响;
简化SQL语句: 有时候需要将查询以后的结果作为一张表来操作,但每次都去写这条查询语句过于麻烦,可以将其设置为视图,简化SQL语句书写;
在面向视图开发时,可以像使用表一样对视图进行增删改查等操作,视图不是存储在内存当中,而是存在硬盘上,不会消失。
五、 DBA命令
数据导入导出(备份):
在windows的dos命令窗口中:
mysqldump 数据库名>导出位置+文件名 -u用户名 -p密码
#eg
mysqldump bjpowernode>D:\bjpowernode.sql -uroot -pbywawayy
数据导入:
需要先登录到mysql服务器,然后创建数据,然后使用数据库:
net start mysql
mysql -uroot -pby2awayy
create table bjpowernode;
use bjpowernode;
#引入导出的文件
source D:\bjpowernode.sql;
六、数据库设计三范式
是数据库表的设计依据。
- 第一范式: 要求任何一张表必须有主键,每一个字段原子性不可再分
- 第二范式: 建立在第一范式的基础上,要求所有非主键字段完全依赖主键,不能产生部分依赖
- 第三范式: 简历在第二范式的基础上,要求所有非主键字段直接依赖主键,不要产生传递依赖
第一范式:
最核心,最重要的范式,所有表的设计都需要满足;
学生编号 | 学生姓名 | 联系方式 |
---|---|---|
1001 | 张三 | zs@qq.com,10010 |
1002 | 李四 | ls@qq.com,10001 |
1001 | 王五 | ww@qq.com,10000 |
以上学生表不满足第一范式:①没有主键 ②练习方式可再细分为邮箱地址和电话号码;
改为以下方式:
学生编号(pk) | 学生姓名 | 邮箱地址 | 电话号码 |
---|---|---|---|
1001 | 张三 | zs@qq.com | 10010 |
1002 | 李四 | ls@qq.com | 10001 |
1003 | 王五 | ww@qq.com | 10000 |
注意: 能否再细分是主观逻辑上判断,取决于我们在操作数据表时的实际应用,如联系方式在逻辑上可分为电话号码,QQ号,微信号,邮箱等,应区分开来。类似姓名这种,理论上可分为姓和名,但我们在逻辑上不这么区分,使用时也一般使用全名,因此不再细分。
第二范式:
建立在第一范式的基础之上,要求所有非主键字段必须完全依赖主键,不产生部分依赖
处理多对多的关系时,采用三张表,两张成员表,一张关系表(外键关联两个成员表的主键)
如:学生表,教师表,教师和学生关系表(一个学生有多个老师,一个老师教多个学生,典型多对多关系)
第三范式:
第三范式建立在第二范式基础上,要求所有非主键字段直接依赖主键,不能产生传递依赖;
学生编号(pk) | 学生姓名 | 班级编号 | 班级名称 |
---|---|---|---|
1001 | 张三 | 01 | 一班 |
1002 | 李四 | 02 | 二班 |
1003 | 王五 | 03 | 三班 |
1004 | 赵六 | 03 | 三班 |
以上表满足第一范式,有主键,所有字段原子性无法再细分
满足第二范式,主键是单一主键,没有产生部分依赖
不满足第三范式,部分字段传递依赖主键: 班级名称依赖班级编号,班级编号完全依赖学生编号;
可改为以下两张表: 一对多(一个班级多个学生)
班级表:
班级编号(pk) | 班级名称 |
---|---|
01 | 一班 |
02 | 二班 |
03 | 三班 |
学生表:
学生编号 | 学生姓名 | 所属班级编号(fk) |
---|---|---|
1001 | 张三 | 01 |
1002 | 李四 | 02 |
1003 | 王五 | 03 |
1004 | 赵六 | 03 |
处理一对一表的设计:
一张表有时候字段太多,过于庞大,会拆分成两张或多张表;
eg:
id(pk) | login_name | login_pwd | name | addr | |
---|---|---|---|---|---|
1 | zhangsan | 123456 | 张三 | 背景 | zs.com |
2 | lisi | 123456 | 李四 | 伤害 | ls.com |
字段太多,可拆分为登录信息表 和 实际信息表
login_table:
id(pk) | login_name | login_pwd |
---|---|---|
1 | zhangsan | 123456 |
2 | lisi | 123456 |
real_table:
id(pk) | name | addr | login_id(fk+unique) | |
---|---|---|---|---|
100 | 张三 | zs.com | 背景 | 1 |
200 | 李四 | ls.com | 伤害 | 2 |
在后面的表中添加外键和唯一约束,保证这张表在拆分后仍然能确保每一行信息的准确性,并且外键必须使用unique约束,否则原表拆分后一行对应多行;
总结:
数据库三范式是理论上的,实践和理论有一定偏差,有时候为了满足客户需求,可以牺牲一定冗余去换执行速度,因为在sql中,表的连接次数越多,效率越低(笛卡尔积)
有的时候可能会存在冗余,但是为了减少表的连接次数,这样做也合理,并且对于开发人员来说,sql语句编写难度降低。
JDBC
JDBC(Java Database Connectivity) java数据库连接
利用java语言/程序连接访问数据库的一门技术(不必通过cmd或者Navicat等工具连接访问数据库,在实际开发中,更过的是通过JDBC)
注册数据库驱动
Class.forName("com.mysql.cj.jdbc.Driver");
获取数据库连接
Connection conn = (Connection)DriverManager.getConnection("jdbc:mysql://localhost:3306/jt_db?characterEncoding=utf-8","root","by2awayy");
获取传输器
Statement stat = conn.createStatement();
该方法返回用于向数据库服务器发送sql语句的Statement传输器对象,该对象上提供了发送sql的方法:
executeQuery(String sql) -- 用于向数据库发送查询类型的sql语句,返回一个ResultSet对象中; executeUpdate(String sql) -- 用于向数据库发送更新(增加,删除,修改)类型的sql语句,返回一个int值,表示影响到的行数;
ResultSet结果集对象
ResultSet对象用于封装sql语句查询的结果,该对象上提供了遍历数据及获取数据的方法。
– 遍历数据行
next() -- 使只想数据行的索引向下移动一行,返回值为true/false
– 获取数据
getInt(int columnIndex) // int类型表示第几列 getInt(String columnIndex) // String表示传入列名,推荐传入列名 getString(int columnIndex) getString(String columnIndex) getDouble... getObject...
释放资源
释放资源时必须按照一定顺序释放,越晚获取的越先关闭
rs.close(); stat.close(); conn.close();
此外,为了避免程序抛出异常,释放资源的代码不会被执行,应该把释放资源的代码放进finally块中。
try{... }catch
数据库连接池
池:一个容器,在内存中的一片空间,用于村粗程序中的数据
连接池: 将连接对象放在一个容器中,当需要连接时,就直接从连接池中获取一个连接进行使用,用完连接后再将连接放回连接池中;
目的时为了减少连接创建和关闭的次数,实现连接的复用。
使用C3P0连接池开发步骤
导入开发包(.jar)
在程序中创建数据库连接池对象
设置数据库连接的基本信息
方式一:(不推荐)
pool.setDriverClass("com.mysql.cj.jdbc.Driver");pool.setJdbcUrl("jdbc:mysql://localhost:3306/jt_db?characterEncoding=utf-8");pool.setUser("root");pool.setPassword("by2awayy");
方式二: (推荐)
在根目录文件夹中设置c3p0.properties文件,添加需要设置的数据库信息
注意: 该配置文件的位置和文件名都是固定的,将来c3p0程序底层会自动到指定位置(src源码目录或者类似的源码目录下)寻找指定名称的文件(c3p0.properties),如果能找到二五年间并读取文件中的配置(配置必须正确),就能成功脸上数据库,能够初始化一批连接放在连接池中,否则会抛出异常
方式三:(推荐)
在类目录下(src或者其他类似的源码目录下),添加一个c3p0-config.xml
注意: 文件名称和文件位置固定;
基于连接池获取一个连接对象,通过连接对象访问数据库
将连接对象还回连接池
esultSet对象中;
executeUpdate(String sql) – 用于向数据库发送更新(增加,删除,修改)类型的sql语句,返回一个int值,表示影响到的行数;
4. ResultSet结果集对象ResultSet对象用于封装sql语句查询的结果,该对象上提供了遍历数据及获取数据的方法。-- 遍历数据行```java
next() -- 使只想数据行的索引向下移动一行,返回值为true/false
– 获取数据
getInt(int columnIndex) // int类型表示第几列
getInt(String columnIndex) // String表示传入列名,推荐传入列名
getString(int columnIndex)
getString(String columnIndex)
getDouble...
getObject...
释放资源
释放资源时必须按照一定顺序释放,越晚获取的越先关闭
rs.close(); stat.close(); conn.close();
此外,为了避免程序抛出异常,释放资源的代码不会被执行,应该把释放资源的代码放进finally块中。
try{... }catch
数据库连接池
池:一个容器,在内存中的一片空间,用于村粗程序中的数据
连接池: 将连接对象放在一个容器中,当需要连接时,就直接从连接池中获取一个连接进行使用,用完连接后再将连接放回连接池中;
目的时为了减少连接创建和关闭的次数,实现连接的复用。
从零开始的MySQL教程——下相关推荐
- 从零开始的MySQL教程——上
MySQL 1. 简介 SQL:美国国家标准化组织的标准化计算机语言,可以用于访问和操作数据库,可以操作所有关系型数据库 创建/ 删除/ 查看数据库 创建/ 删除/ 查看/ 修改表 新增/ 修改/ 删 ...
- mysql-win安装教程,WINDOWS下安装MYSQL教程详解
1.下载安装包 2.配置环境变量 2.1 解压所下载的压缩包 2.2 环境变量 win 10 电脑 这么进去 3.生成data文件 在你解压的目录下,eg:F:\Program Files\mysql ...
- nginx mysql 安装_CentOS7下安装Nginx+MySQL教程
首先我们需要安装nginx的yum源 警告:/var/tmp/rpm-tmp.aRXWtf: 头V4 RSA/SHA1 Signature, 密钥 ID 7bd9bf62: NOKEY 准备中... ...
- mysql安装 2018最新安装mysql教程及遇到的问题解决Windows下
原文作者:aircraft 原文地址:https://www.cnblogs.com/DOMLX/p/8094659.html 今天因为换了个LINUX系统 把我的E盘不小心给卸载了 结果还是不能用 ...
- access 导入 txt sql语句_从零开始学习 MySQL 系列索引、视图、导入和导出
阅读本文大概需要 8 分钟 前言上篇文章我们学习了数据库和数据表操作语句,今天我们学习下数据库索引,视图,导入和导出的知识.作为基础篇,不会涉及到关于索引和视图的高级应用和核心概念,但是基本操作大家会 ...
- mysql导入dat文件_从零开始学习 MySQL 系列--索引、视图、导入和导出
前言 上篇文章我们学习了数据库和数据表操作语句,今天我们学习下数据库索引,视图,导入和导出的知识. 作为基础篇,不会涉及到关于索引和视图的高级应用和核心概念,但是基本操作大家会了解,尤其是关于索引的内 ...
- 史上最简单MySQL教程详解(进阶篇)之存储引擎介绍及默认引擎设置
什么是存储引擎? MySQL存储引擎种类 MyISAM 引擎 InnoDB引擎 存储引擎操作 查看存储引擎 存储引擎的变更 修改默认引擎 什么是存储引擎? 与其他数据库例如Oracle 和SQL Se ...
- select计数语句_从零开始学 MySQL SELECT 语句详解
阅读本文大概需要 7 分钟 前言上篇文章我们学习了 MySQL 的五种约束,今天这篇文章我们来学习下 SELECT 语句.在数据库操作语句中,使用最频繁,也被认为最重要的是 SELECT 查询语句.在 ...
- php导出数据库的指定表数据,MYSQL教程mysql数据库导出指定表数据的方法
<MYSQL教程mysql数据库导出指定表数据的方法>要点: 本文介绍了MYSQL教程mysql数据库导出指定表数据的方法,希望对您有用.如果有疑问,可以联系我们. 导读:linux下导出 ...
最新文章
- [存储过程]中的事务(rollback)回滚
- 经典:某程序员手机里保存的五十条牛B短信
- java接口fastjson_走进Java接口测试之fastjson指南
- 计算机等级ms答题演示,计算机等级一级MS Office考试考题:第六套演示文稿题
- 从徐飞的文章《Web应用的组件化开发(一)中窥视web应用开发的历史
- WebView与js的交互
- 细谈eclipse PDT开发WordPress插件
- 线程的共享资源和私有资源
- myeclipse黑色主题怎么还原
- yagmail发送邮件
- opencv之图片处理看这一篇就够了(一)
- 三色SM认证人脸动态视频制作教程
- 差分 离散化 (线段树优化lazy标记)2018ICPC SouthEastern Fishermen
- Python:实现collatz sequence考拉兹序列算法(附完整源码)
- 几种修复照片画质的方法
- 简单的理解unicode和utf-8的关系
- 更改分类算法的阙值的资料
- 字节跳动校招 抖音电商前端 三面面经
- 为什么使用计算机辅助翻译工具中文译文,TCloud计算机辅助翻译工具
- 上线MSF(Metasploit)的几种常见方式