mysql 学习、复习资料整理详细
- 1、数据库基础
- 1.1 数据库设计遵循的原则
- 1.2 数据库范式
- 1.2 数据库完整性的实现
- 2、mysql特点
- 3、事务
- 3.1 事务的四大特性 – ACID
- 3.2 并发事务问题
- 3.3 事务的四大隔离级别
- 3.4 事务隔离级别操作sql
- 3.5 事务原理 – LBCC MVCC
- 3.4.1 行的隐藏列
- 3.4.2 ReadView
- 3.4.3 MVCC在四种隔离级别下的区别
- 3.5 undo log、binlog、redo log
- 3.6 事务提交过程
- 3.7 事务的操作sql📌
- 3.8 MySQL中是如何实现事务提交和回滚的?
- 4、数据库主从读写
- 4.1 数据库主从复制原理
- 4.2 数据库主从读写延迟解决方案
- 5、锁
- 6、主键、外键
- 6.1 主键
- 6.1.1 主键sql
- 6.1.2 主键自增设置
- 6.1.3 自增主键与uuid区别
- 6.1.4 主键与索引的区别
- 6.2 外键
- 7、索引
- 7.1 索引机制
- 7.2 聚集索引、非聚集索引、覆盖索引、联合索引 辅助索引
- 7.3 前缀索引 全部索引
- 8、存储引擎
- 9、mysql的连接类型 - 7种
- 10、分库 分表 分页
- 11、聚合函数
- 12、查询
- 12.1 联表查询
- 12.2 左连接 右连接
- 12.3 where having
- 12.4 drop delete truncate
1、数据库基础
1.1 数据库设计遵循的原则
设计数据表的时候,要考虑很多的问题:
(1) 用户需要哪些数据,我们在数据表中要保存哪一些数据
(2)怎么保证数据表中的数据的正确性
(3)如何降低数据表的冗余度
(4)开发人员怎么才能更方便的使用数据库
如果数据库设计得不合理的话,可能导致下面的几种问题:
(1)设计容易,信息重复,存储空间浪费
(2)数据更新,插入,删除的异常
(3)不能正确表示信息
(4)丢失有效信息
(5)程序性能差
我们可以看出设计良好的数据库是很重要的,它有下面的优点:
(1)节省数据的存储空间
(2)能够保证数据的完整性
(3)方便进行数据库应用系统的开发
设计数据库,我们得重视数据表的设计,为了建立冗余度小,结构合理的数据库,设计数据库必须遵循一定的规则。
1.2 数据库范式
关系型数据库中,关于数据表设计的基本原则,规则就称为范式,范式是我们在设计数据库结构过程中需要遵循的规则和指导方法。
范式的详细介绍,参考链接:数据库的三大范式
1.2 数据库完整性的实现
- 数据库表设计遵循三大范式原则 ;
- 可以使用约束实现数据完整性,一个约束只能对一个表的一个列产生作用,如
- 可以使用规则和默认值,规则和默认值在创建了以后,它不属于某个表,只有在绑定了命令了以后才会发生关系,可以绑定到多个表多个列中。
详细描述参考链接:数据库—怎样实现数据完整性
2、mysql特点
- 功能强大:MySQL提供了多种数据库存储引擎,各个引擎各有所长,适用于不同应用场合。用户可以选择最合适的引擎以得到最高性能,这些引擎升值可以应用处理每天访问量数亿的高强度Web搜索站点。MySQL支持事务、视图、存储过程和触发器等。
- 支持跨平台:MySQL支持至少20种以上的开发平台,包括Linux、Windows、FreeBSD、IBMAIX、AIX和FreeBSD等。这使得在任何平台下编写的程序都可以进行移植,而不需要对程序做任何修改。
- 运行速度快:高速是MySQL的显著特性。在MySQL中,使用了极快的B书磁盘表(MyISAM)和索引压缩;通过使用优化的单扫描多连接,能够极快的实现连接;SQL函数使用高度优化的类库实现,运行速度极快。
- 支持面向对象:PHP支持混合编程方式。编程方式可分为纯粹面向对象、纯粹面向过程、面向对象与面向过程混合3种方式。
- 安全性高;灵活安全的权限和密码系统允许主机的基本验证。连接到服务器时,所有的密码传输均采用加密形式,从而保证了密码的安全。
- 成本低:MySQL数据库是一种完全免费的产品,用户可以直接从网上下载。
- 支持各种开发语言:MySQL为各种流行的程序设计语言提供支持,为他们提供了很多的API函数。
- 数据库存储容量大:MySQL数据库的最大有效容量通常是由操作系统对文件大小的限制决定的,而不是由MySQL内部限制决定的。InnDB存储引擎将InnDB表保存在一个表空间内,该表空间可由数个文件创建,表空间的最大容量为64TB,可以轻松处理拥有上万条记录的大型数据库。
- 支持强大的内置函数:PHP中提供了大量内置函数,几乎涵盖了Web应用开发中的所有功能。它内置了数据连接、文件上传等功能,MySQL支持大量的扩展库,如MySQLi等,为快速开发Web应用提供方便。
3、事务
事务指的是一组命令操作,在执行的过程中,要么全部成功,要么全部失败。
由引擎层支持事务,MyISAM就不支持事务,而InnoDB是支持事务的。
3.1 事务的四大特性 – ACID
事务具有以下四大特性(ACID):
- 原子性(Atomicity):
指事务不可分割,要么全部成功,要么全部失败,不可能存在部分成功或部分失败的情况。如果执行某一条语句失败后,将会触发之前所有执行过的语句的回滚,因此靠的是undo log。 - 一致性(Consistency):
在事务执行前后,数据的完整性没有遭到破坏。一致性是mysql追求的最终目标,需要数据库层面与应用层面同时来维护。需要先满足原子性、隔离性与持久性,同时也需要应用层面做保障,即在应用层面对数据进行检验。 - 隔离性(Isolation):
事务之间是隔离的,并发执行的事务之间不存在互相影响,mysql通过锁以及MVCC来保证隔离性。 - 持久性(Durability):
事务一旦提交,那么对数据的操作就是永久性的,即使接下来数据库宕机也不会有影响。mysql是通过redo log来实现宕机恢复的,而binlog主要是用来误删恢复与主从复制的。
3.2 并发事务问题
并发事务问题就是多个事务同时执行的时候出现的问题
当事务存在并发时,就会产生以下问题:
- 脏读:即读取到别的事务未提交的数据。
例如:A事务读取B事务尚未提交的数据,此时如果B事务发生错误并执行回滚操作,那么A事务读取到的数据就是脏数据。这种情况常发生于转账与取款操作中。 - 不可重复读:即某个事务前后多次读取,数据内容不一致。
例如:事务A在执行读取操作,由整个事务A比较大,前后读取同一条数据需要经历很长的时间 。而在事务A第一次读取数据,比如此时读取了小明的年龄为20岁,事务B执行更改操作,将小明的年龄更改为30岁,此时事务A第二次读取到小明的年龄时,发现其年龄是30岁,和之前的数据不一样了,也就是数据不重复了,系统不可以读取到重复的数据,成为不可重复读。 - 幻读:即某个事务前后多次读取,读到的数据总量不一致。
例如:事务A在执行读取操作,需要两次统计数据的总量,前一次查询数据总量后,此时事务B执行了新增数据的操作并提交后,这个时候事务A读取的数据总量和之前统计的不一样,就像产生了幻觉一样,平白无故的多了几条数据,称为幻读。
3.3 事务的四大隔离级别
事务隔离级别就是多个事务执行时,互不影响的程度,事务隔离级别不同,出现的事务并发问题就不一样。
事务隔离级别,就是在不同程度上解决上述脏读、不可重复读、幻读的问题。有四种隔离级别,分别是
- 读未提交(Read Uncommitted):
在这种隔离级别下,所有事务能够读取其他事务未提交的数据。读取其他事务未提交的数据,会造成脏读。因此在该种隔离级别下,不能解决脏读、不可重复读和幻读。读未提交可能会产生脏读的现象,那么怎么解决脏读呢?那就是使用读已提交。 - 读已提交(Read Committed):
在这种隔离级别下,所有事务只能读取其他事务已经提交的内容。能够彻底解决脏读的现象。但在这种隔离级别下,会出现一个事务的前后多次的查询中却返回了不同内容的数据的现象,也就是出现了不可重复读。
这是大多数数据库系统默认的隔离级别,例如Oracle和SQL Server,但mysql不是。已提交可能会产生不可重复读的现象,我们可以使用可重复读。 - 可重复读(Repeatable Read):
在这种隔离级别下,所有事务前后多次的读取到的数据内容是不变的。也就是某个事务在执行的过程中,不允许其他事务进行update操作,但允许其他事务进行add操作,造成某个事务前后多次读取到的数据总量不一致的现象,从而产生幻读。
这才是mysql的默认事务隔离级别可重复读依然会产生幻读的现象,此时我们可以使用串行化来解决。 - 串行化(Serializable):
在这种隔离级别下,所有的事务顺序执行,所以他们之间不存在冲突,从而能有效地解决脏读、不可重复读和幻读的现象。但是安全和效率不能兼得,串行化会大大降低数据库的性能,一般不使用这种级别。
下面用一张表格来表示他们能够解决的问题,x代表未解决,√代表能够解决。
注意:隔离级别越高,数据越安全,但是性能越低,在开发时应根据实际情况选择合适的隔离级别。
当然,以上所说的隔离级别及当前级别存在的问题只是一种规范,不同的数据库厂商可以有不同的实现。
例如在mysql的可重复读的级别上,使用临键锁的方式就已经解决了幻读的问题。
3.4 事务隔离级别操作sql
- 查看事务隔离级别:
SELECT @@TRANSACTION_ISOLATION;
默认级别为Repeatable read。
- 设置事务隔离级别:
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL 隔离级别;
SESSION表示当前设置的隔离级别只对当前会话有效,即当前建立的数据库连接。GLOBAL表示全局有效。
3.5 事务原理 – LBCC MVCC
mysql为了实现以上隔离级别,提出了LBCC(Lock-Based Concurrent Control,基于锁的并发控制)与MVCC(Multi-Version Concurrent Control,基于多版本的并发控制)。
在LBCC中,读写冲突,会使用诸如记录锁、间隙锁与临键锁等锁来实现数据的并发安全,因此读写性能不高。
关于锁的分类,可以参考:谈谈锁的类型
在MVCC中,读写不冲突,记录每一行的多个版本,来避免在多个事务之间的竞争。以空间换时间的思路,极大地提高了读写性能。
MVCC主要靠undo log版本链与ReadView来实现。
对于MVCC,简单来讲,就是mysql保存了一行数据在多个时间点的快照,是一种使用空间换取时间的策略,能做到读(快照读,可以理解就是普通的select语句)写不加锁。你可以暂时理解为,每一份快照包含了一行undo log日志,各个版本的快照。
3.4.1 行的隐藏列
在数据库中的每一行上,除了存放真实的数据以外,还存在着3个隐藏列:row_id、trx_id与roll_pointer。
- row_id,行号
如果当前表有整数类型的主键,则row_id就是主键的值。
如果没有整数类型的主键,则mysql会按照字段顺序选择一个非空的整数类型的唯一索引作为row_id。
如果mysql没有找到,则会自动生成一个自动增长的整数作为row_id。
那row_id和今天的MVCC有什么关系呢?只能说毫无关系。 - trx_id,事务号
当一个事务开始执前,mysql会为这个事务分配一个全局自增的事务id。
之后该事务对当前行进行的增、删、改操作时,都会将自己的事务id记录到trx_id中。 - roll_pointer,回滚指针
事务对当前行进行改动时,会将旧数据写入进undo log中,再将新数据写入当前行,且当前行的roll_pointer指向刚才那个undo log,因此可以通过roll_pointer找到该行的前一个版本。
当一直有事务对该行改动时,就会一直生成undo log,因此roll_pointer可以将这些不同版本的undo log串联起来,形成undo log版本链。
3.4.2 ReadView
首先需要理解一下快照读与当前读
- 快照读:
简单的select查询,即不包括 select … lock in share mode, select … for update,可能会读到数据的历史版本。 - 当前读:
以下语句都是当前读,总是读取最新版本,会对读取的最新版本加锁。
select ... lock in share mode
select ... for update
insert
update
delete
在事务执行每一个快照读或事务初次执行快照读时,会生成一致性视图,即ReadView。
ReadView的作用是,判断undo log版本链中的哪些数据对当前事务可见。
3.4.3 MVCC在四种隔离级别下的区别
所以,MVCC只在RC与RR级别下工作,区别在于生成ReadView的频率不同。
3.5 undo log、binlog、redo log
详情参考文章:数据库日志:binlog、redo log、undo log详解
3.6 事务提交过程
- 事务执行先记录 undo/redo log,确保日志刷到磁盘上持久存储。更新数据记录,缓存操作并异步刷盘。 如果开启了 binlog,将事务日志持久化到 binlog。
- 提交事务,在 redo log 中写入 commit 记录。在 mysql 执行事务过程中如果因故障中断,可以通过 redo log 来重做事务或通过 undo log 来回滚,确保了数据的一致性。只要 binlog 没写成功,整个事务是需要回滚的,而 binlog 写成功后即使 Mysql Crash 了都可以恢复事务并完成提交。
MySQL是通过WAL方式,来保证数据库事务的一致性和持久性,即ACID特性中的C(consistent)和D(durability)。
WAL(Write-Ahead Logging)是一种实现事务日志的标准方法,具体而言就是:
1、修改记录前,一定要先写日志;
2、 事务提交过程中,一定要保证日志先落盘,才能算事务提交完成。
通过WAL方式,在保证事务特性的情况下,可以提高数据库的性能。从上述流程可以看出,提交过程中,主要做了4件事情:
1、清理undo段信息,对于innodb存储引擎的更新操作来说,undo段需要purge,这里的purge主要职能是,真正删除物理记录。在执行delete或update操作时,实际旧记录没有真正删除,只是在记录上打了一个标记,而是在事务提交后,purge线程真正删除,释放物理页空间。因此,提交过程中会将undo信息加入purge列表,供purge线程处理。
2、释放锁资源,mysql通过锁互斥机制保证不同事务不同时操作一条记录,事务执行后才会真正释放所有锁资源,并唤醒等待其锁资源的其他事务;
3、刷redo日志,前面我们说到,mysql实现事务一致性和持久性的机制。通过redo日志落盘操作,保证了即使修改的数据页没有即使更新到磁盘,只要日志是完成了,就能保证数据库的完整性和一致性;
4、清理保存点列表,每个语句实际都会有一个savepoint(保存点),保存点作用是为了可以回滚到事务的任何一个语句执行前的状态,由于事务都已经提交了,所以保存点列表可以被清理了。
3.7 事务的操作sql📌
- 查看事务提交方式:
SELECT @@autocommit;
默认值为1,表示执行完SQL语句后自动提交,若在中间发生了错误,则会提交错误之前的所有SQL - 设置事务提交方式:
SET @@autocommit = 0;
@@autocommit值为0表示手动提交事务。 - 提交事务:
COMMIT;
在开启事务的SQL语句执行后,手动COMMIT提交事务。注意,一旦COMMIT后就不能回滚事务,这也对应了事务特性的最后一点----持久性 - 回滚事务:
ROLLBACK;
在事务执行完毕,没有提交的时候,可以使用ROLLBACK进行回滚事务,撤销对数据的操作。 - 开启事务:
START TRANSACTION 或 BEGIN
开启事务后,后面对数据库的修改操作就需要手动提交(COMMIT)和回滚(ROLLBACK)。
3.8 MySQL中是如何实现事务提交和回滚的?
为了保证数据的持久性,数据库在执行SQL操作数据之前会先记录redo log和undo log
redo log是重做日志,通常是物理日志,记录的是物理数据页的修改,它用来恢复提交后的物理数据页
undo log是回滚日志,用来回滚行记录到某个版本,undo log一般是逻辑日志,根据行的数据变化进行记录
redo/undo log都是写先写到日志缓冲区,再通过缓冲区写到磁盘日志文件中进行持久化保存
undo日志还有一个用途就是用来控制数据的多版本(MVCC)
简单理解就是:
redo log是用来恢复数据的,用于保障已提交事务的持久性
undo log是用来回滚事务的,用于保障未提交事务的原子性
4、数据库主从读写
4.1 数据库主从复制原理
参考链接:数据库的主从复制原理(超级详细)
4.2 数据库主从读写延迟解决方案
参考链接:数据库主从读写延迟解决方案
5、锁
关于锁的分类,可以参考:谈谈锁的类型
6、主键、外键
6.1 主键
primary key用来唯一的约束字段里面的数据,不能重复,不能为空,一张表中最多只能有一个主键,而且主键所在的列通常是整数类型。
注意:主键所在的列不能重复,不能为空。
6.1.1 主键sql
- 主键创建
在创建表的时候,在字段之后,使用primary key(主键字段列表)来创建主键,如果有多个字段作为主键,可以使用复合主键。 - 追加创建主键
格式为:alter table 表名 add primary key(字段列表)
- 删除主键
格式为:alter table 表名 drop primary key;
6.1.2 主键自增设置
在数据库应用中,经常希望在每次插入新纪录时,系统自动生成字段的主键值。可以通过为表主键添加AUTO_INCREMENT关键字来实现。
默认情况下,在MYSQL中自增id的初始值是1,每新增一条记录,字段值自动加1.
一个表只能有一个字段属用AUTO_INCREMENT约束,且该字段必须为主键的一部分。AUTO_INCREMENT约束的字段可以是任何整数类型(TINTINT、SMALLINT、INT、BIGINT等)
添加自增的格式为:字段名 数据类型 AUTO_INCREMENT
6.1.3 自增主键与uuid区别
6.1.4 主键与索引的区别
6.2 外键
参考链接:MySQL中的外键(foreign key)
7、索引
7.1 索引机制
参考链接:MYSQL 索引机制-B+TREE
7.2 聚集索引、非聚集索引、覆盖索引、联合索引 辅助索引
1、参考链接:聚集索引、非聚集索引、覆盖索引的总结
2、参考链接:mysql聚集索引、辅助索引、覆盖索引、联合索引的使用
3、参考链接:MySQL索引之联合索引
7.3 前缀索引 全部索引
参考链接:MySQL字符串前缀索引详解
8、存储引擎
参考链接:一文带你看懂 MySQL 存储引擎
9、mysql的连接类型 - 7种
参考链接:Mysql中的七种常用查询连接详解
10、分库 分表 分页
参考链接:MySQL分页方法
11、聚合函数
参考链接:MySQL聚合函数
12、查询
12.1 联表查询
参考链接:MySQL联表查询
12.2 左连接 右连接
**1. 左连接:**以左表为参照,显示所有数据,右表中没有则以null显示
**2. 右连接:**以右表为参照显示数据,左表中没有则以null显示
左连接where只影向右表,右连接where只影响左表。
参考链接:mysql数据库的左连接,右连接,内链接有何区别
12.3 where having
参考链接:Mysql中where和having用法及区别
12.4 drop delete truncate
参考链接:MySQL删除表操作(delete、truncate、drop的区别)