mysql
介绍
mysql三大范式
第一范式:保证每一列不可再分
第二范式:在一范式基础上,每张表只描述一件事情
第三范式:在一二范式基础上,需要确保数据表中的每一列数据都和主键直接相关,而不是间接相关
规范性和性能的问题:因为遵循范式会让表的数量增加,从而影响性能,所以一般需要综合考虑。(关联查询的表,不得超过三张表)
数据存储引擎
InnoDB
支持事务和聚集索引,行级锁,外键
MyIsam
支持全文索引(FULLTEXT),使用非聚集索引
全文索引主要用来查找文本中的关键字,而不是直接与索引中的值相比较
memory
基于内存,速度很快,断电数据丢失
事务
定义
要么全部执行成功,要么全部执行失败
mysql操作事务
mysql默认开启了事务自动提交,每条语句都是一个事务(autocommit =1)
手动执行事务步骤
1.关闭自动提交:set autocommit = 0;
2.开启事务:start TRANSACTION (下面语句都在一个事务中);
3.执行的命令;
4.提交:commit(持久化(成功))
5.回滚:ROLLBACK(回到原来的样子(失败))
6.最后开启自动提交:set autocommit =1(了解:SAVEPOINT 可以设置事务保存点,可回滚到保存点)
并发事务问题(解决对应4中隔离级别)
脏写
定义:一个事务写覆盖另一个事务的写。(例如,同时存款,一个事务回滚,会覆盖另一个事务存的钱。导致少存)
解决:通过事务隔离级别:读未提交read uncommitted(修改数据会加写锁,一个事务写数据未提交或者回滚前其他事务不能写,解决脏写)
脏读
定义:读到其他事务修改但未提交的数据。
解决:通事务隔离级别:读已提交read committed(读数据加读锁(只在读的时候加),读写锁不能同时存在,一个事务写数据未提交前其他事务不能读写,解决脏读)
不可重复读
定义:在一个事务内多次读取的结果不同(多次读的间隙其他事务更新了数据)
解决:通过事务隔离级别:可重复读repeatable read(InnoDB默认)(修改数据会加写锁,读数据加读锁。读数据时加的读锁在事务结束前不会释放,可以防止其他事务写数据。解决不可重复读)
mysql InnoDB不是通过锁,而是通过MVCC一个事务里只会获取一次read view副本,来保证一个事务多次读取数据一致
幻读
定义:在一个事务内多次读取的数据行数不同(其他事务插入或删除了数据)
解决:通过事务隔离级别:串行化serializable(事务串行,能够解决所有因为事务并发带来的问题)
MySQL中mvcc快照读能解决幻读,当前读通过加间隙锁来解决。间隙锁通过对查询的范围加锁来避免幻读)
说明
隔离级别越高,事务安全性越高,但事务并发性能越低。开发中,我们要保证数据库的性能,所以建议事务在程序中控制。
数据一致性
CAP理论
C:强一致性(系统时刻都保持一致性)
A:可用性(每个操作在一定时间内返回结果)
P:分区容错性(系统存在网络分区的情况下,仍能接受请求)
CAP意义:CAP是分布式系统需要考虑的三个问题,只能同时满足两个
BASE理论:是CAP理论中AP的延申,强调可用性。它的核心是基本可用和最终一致性
事务特性:ACID原则
原子性:要么都成功,要么都失败
一致性:事务前后的数据完整性要保持一致(A转B50,最后A少50,B多50)
隔离性:事务产生并发时候,互不干扰
持久性:事务一旦提交就不可逆转,被持久化到数据库中
锁
介绍
对数据加锁是为了解决事务的隔离性问题,如果条件命中索引节点对应 行锁,未命中索引节点就是锁住整颗b+树,也就是表锁
分类
属性分类
共享锁(读锁)
多个事务共享读锁。都可以访问数据,但不能修改。(解决脏读,重复读问题)
排他锁(写锁)
只有一个事务能够获得排他锁,其他事务都不能获取该行的锁。InnoDB会对update\delete\insert语句自动添加排他锁。(解决脏写,脏读问题)
按粒度分类
表锁
粒度大,加锁资源开销小,易冲突
行锁
粒度小,加锁资源开销大,不容易冲突
记录锁:记录锁的范围只是表中的某一条记录
间隙锁:锁住的是表记录的某一个区间(解决幻读,是可重入锁)
临键锁:临键锁会把查询出来的记录,包括两边相邻的下一个区间锁住。
按锁的状态分类
意向共享锁:加共享锁之前,需要获得这个表的意向共享锁。
意向排它锁:加排他锁之前,需要获得这个表的意向排他锁。
为什么需要:a事务对表加锁前,需要检查每个节点是否已经加锁,导致性能很低。所以当一个事务对某表加锁后就设置一个意向锁,通过意向锁就能快速判断改表是否加锁。
自增锁
通常是针对MySQL当中的自增字段。如果有事务回滚这种情况,数据会回滚,但是自增序列不会回滚。
全局锁
全局锁:加锁之后整个数据库实例都处于只读状态。所有的数据变更操作都会被挂起。一般用于全库备份的时候。
MVCC
介绍
MVCC由来(优点):数据库多数是查询操作,由于加读锁实现的事务隔离会降级数据库性能。MVCC 是InnoDB中多版本控制,解决加读锁导致的性能问题(具体是通过保存数据的历史版本,根据比较数据的版本号来决定数据的是否显示,不需要加读锁的情况就能达到事务的隔离效果)
事务版本号
事务开启前会获得一个自增的事务id(通过事务id判断事务执行的先后顺序)
表的隐藏列
DB_TRX_ID:记录操作该表事务的ID
DB_ROLL_PTR:指向undo log中该表上一版本的指针
DB_ROW_ID:隐藏ID。(mysql会为每张表建一个主键索引,如果没主键,会找表中的唯一键(就是表中无重复数据的字段)。如果没有唯一键,mysql会自动生成一个隐藏主键)
undo log
作用:表修改前会把数据先拷贝到undo log中,用于回滚和MVCC多版本控制
当前读:读取数据库最新的数据,需要加锁
快照读:快照读是从undo log中读取的历史版本数据,不用加锁,在普通select语句中采取的是快照读,自己加锁的select语句中是当前读(增删改操作是最新数据,不是undolog中的历史版本)
read view
介绍
每个事务开启后会得到一个read_view,主要保存的是当前活跃事务的id号(未提交的,也就是需要与当前事务隔离的事务id)
四个重要属性
trx_ids
当前活跃的事务号合集
low_limit_id
当前最大事务版本号+1
up_limit_id
当前活跃事务中最小版本号
creator_trx_id
创建该read view的事务版本号
Innodb实现MVCC原理
事务读取数据流程
1.事务开启后,会先获得事务版本号和read view。2.接着查询数据,将查询的数据与read view 进行匹配,如果不符合再从undo log中获取历史版本数据进行匹配,最后返回数据(没有匹配数据返回null)
read view 匹配条件
查询的数据的事务ID
当前活跃事务中最小版本号 <=数据的事务ID<当前系统最大事务版本号+1时:则将数据的事务ID与活跃事务集合里匹配,若在就不显示,若不在就可以显示。(活跃事务集合中不包含当前事务id)
不同隔离级别下MVCC工作方式
读未提交级别的事务不会获取read view 副本,所以存在脏读
读已提交级别的事务每次查询都会获得一个readview副本,所以存在不可重复读的问题
可重复读级别的一个事务里只获取一个read view副本
MVCC是否能解决幻读
快照读的情况下可以避免幻读问题(一个事务只会获取一次readView副本)。在当前读的情况下存在幻读问题,可以通过间隙锁来解决幻读问题的。
索引
介绍
定义:MySQL索引的建立对于MySQL的高效运行是最重要的,索引可以大大提高MySQL的查询速度。
分类
逻辑分类
普通索引(KEY/INDEX)
普通索引是最基本的索引,它没有任何限制,值可以为空,仅加速查询。
唯一索引(UNIQUE KEY)
索引列的值不同(可以有一个空值,空值跟其他值也不同)。
主键索引(PRIMARY KEY)
主键索引是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。
联合索引
组合索引指在多个字段上创建的索引,只有在查询条件中包含了创建索引时的第一个字段,索引才会被使用(遵循最左前缀原则)
全文索引(FULLTEXT)
全文索引主要用来查找文本中的关键字,而不是直接与索引中的值相比较(特定的数据库引擎才有,如MyISAM)
普通索引和唯一索引选择:优先选择普通索引,普通索引可以配合changebuffer,在更新时速度较快(唯一索引不能更新到changebuffer是因为它值必须唯一,所以需要判断是否有冲突,没冲突再插入)
按存储形式分类
聚集索引:数据页和索引页放一起(InnoDB)。注意:除了主键索引外,其他索引的叶子节点没有存实际值,是因为这样每建一个索引都复制一份数据非常占空间。还有就是更新某值的时候所有索引对应的数据都要修改值。所以实际存的为索引的值和对应的主键,当找到某索引时,再通过其主键去主键索引找对应的全部值(这就称为:回表)
非聚集索引:数据页和索引页分开存放,叶子节点存的是数据的地址信息(MyIsam)。非聚集索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同
按数据结构分类
Hash类型
速度快,但是不支持范围查询,所以不常用
b+树
b+树一般三层,每个节点16kb,对应一次IO。数据只存在叶子节点。非叶子节点存放索引。叶子节点间通过双向链表连接。
为什么用b+树不用b树:1.非叶子节点不存数据,能存更多的索引,对应读写磁盘代价更低。2. 非叶子节点不存数据,所以查询比b树更稳定。3. 叶子节点双向链表连接,所以支持范围查询
结构具体为:叶子节点为数据页,其他节点为索引页。数据页中有页目录和对应数据,数据按索引顺序存放(数据页间双向链表,页中数据单向链表),每个二层索引页中存放的是若干页地址,一个页地址对应一个数据页中页目录的起始地址。一层索引页中存放的若干页地址,一个页地址对应二层索引页中一个索引页中的第一个页地址。
可存放千万行的数据:假如索引为int类型占4字节,指针占6字节,两层可以指向的数据页就是(161024/10 )^2=2683044页。每页16kB,如果一条记录占1kb,那就能存268304416=42,928,704(四千多万条数据)
各种树
二叉树:缺点:树的高度不稳定,可能变成链表,影响效率。
平衡二叉树:左右子树高度差不超过1
平衡二叉查找树:平衡二叉树基础上保证,中序遍历为递增。(平衡算法有:红黑树,AVL树)
红黑树:增删差时间复杂度为logn(子树高度差可能大于1,不是严格平衡二叉树)。特征:1.红节点的孩子是黑节点,2. 叶子节点不存储数据空节点,3. 叶节点和根节点为黑色。4.从任一节点出发到任意叶子节点的路径,黑色节点的数量是相等的。(所以去掉红色节点后长度不超过log(n+1),又因为两个红色节点间一定有黑色节点,所以总高度不超过2log(n+1))。
AVL树:相对红黑树高度控制更严格,查找效率小于logn。但增加删除的调整都相对复杂(所以一般用红黑树)
B树:一个节点有两个或多个孩子节点,且一个节包含多个元素(可设置),节点间和节点内部元素都是排好序的(可设置)。
B+树:相对于B树,叶子节点包含所有元素,且叶子节点间有指针。
引入:1. 为了保证节点均匀分布,就有了平衡二叉树。2. 为了减少树的高度和一次IO读取更多的数据引入B树。3. B+树在B树的基础上,在查询的稳定性 和排序方面进行了优化,因为B+树所有数据都会保存到叶子节点,且叶子节点有序。
索引失效
查不到造成
最左前缀原则:联合索引必须遵循最左前缀原则,是因为比如联合索引字段为a,b,c。它是在a排好序的基础上再排b,所以如果查询条件没有a的话,是不能通过b来走索引的
索引查询更慢造成
范围查询可能走索引也可能不走索引。(因为如果查询范围数据量大,而且索引中不包含需要查询的字段。会导致大量的回表操作,速度还不如全表扫描。)(但是如果查询的字段在索引中,这个时候就可以走索引了,因为不用回表操作了。这个称为覆盖索引)
索引下推
MySQL 5.6 提出,目的是减少回表次数(是联合索引的情况下),具体做法是:可以在非聚簇索引遍历过程中,对索引中包含的字段先做判断,过滤掉不符合条件的记录,再进行回表,从而减少回表次数。
如联合索引为name 和age两个字段, 5.6之前根据最左匹配原则,是在联合索引中找到符合name的主键,然后回表,server层再对符合age的进行过滤。5.6过后是回表前就先对age进行过滤
回表
非主键索引叶子节点只存了索引字段和主键字段,所以如果查询的字段不在索引字段中就需要通过主键去查需要的字段,这个就称为回表
数据库优化
sql优化
sql慢查询的定位
在mysql中开启对应的“慢查询日志”功能,查询慢的sql语句会被日志记录下来(默认10秒认为慢sql,可以设置)
sql语句性能分析
在SQL语句前加上一个explain关键字,就可以得到SQL的执行计划,里面记录了各种信息(如是否使用索引,扫描了多少记录等)
优化细则
尽可能使用覆盖索引:就是我们查询的列数据通过索引就可以获得数据,不用回表(只有主键索引是聚集索引,其他索引没有全部数据,只有对应索引数据和主键,所以如果索引数据不包含需要查询列的数据,需要根据主键再通过主键索引查询。)
最左匹配原则:模糊查询(如like)时,只有从左边匹配时才能用到索引(最左前缀原则)。(如何判断索引命中了多少个:通过sql性能分析explain中 key_len 的长度,和对应索引字段长度比较)
避免隐式转换:例子:1.索引类型为varcchar,查询时匹配条件给的数字。2.查询时把函数套在字段上,没有套在匹配条件上(这样会把数据库对应字段全部转换再和匹配条件对比)
只获取必要的列,尽量不使用select :即影响查询效率,也占不必要内存
减少数据加锁时间和范围:1. 锁一条记录使用行锁不使用表锁。2. 查询语句放事务外,可以减少事务的时间从而减少事务中修改语句加锁时间。
尽量保证join、oder by、group by的字段使用索引:1.join 的字段使用了索引,就会使用高效的Index Nested-Loop Join 算法。2.sort、group by 字段使用了索引就可以利用b+树已经排好序的特性
join用小结果集驱动大结果集。join是先查出两张表,通过一个双层循环来遍历外层表 与内层表匹配的过程,如果关联的表有索引,假如小表500条,大表1000条。左表驱动匹配次数就是500索引高度,反之就是1000索引高度
表设计优化
索引设计
适合建索引:对经常要查询的列、需要经常排序的列和要求值唯一的列建立索引(索引b+树排好序)
不适合建索引:大字段的列,离散性不高的字段(如只有男女),频繁修改的字段(索引放内存,大字段占内存。区分度不高建索引无意义。频繁修改的字段也会频繁修改索引,影响效率)
多使用联合索引:因为组合索引匹配出来的数据更少
表设计
字段冗余:同个字段出现在多张表,减少联表的操作。(如join 查询,匹配的数据量是呈笛卡尔积的上升的)
表冗余:可以多建表来保存一些统计数据,提高效率。
数据冷热分离:对于数据量很大的表,根据表中数据的查询量把数据拆分成多张表。
数据库架构优化
硬件方面
硬件升级
资源池化
解释:应用和数据库频繁建立连接非常消耗性能,可以通过连接池技术来优化
连接池创建思路:1.创建n个初始连接。2.请求连接时,连接池有空闲连接则返回一个。3.如果没有空闲连接且未达连接池最大值,就新建一个返回。4.如果没有空闲且达最大连接。再看任务队列,如果未满则提交一个任务放到队列里面,在有限的超时时间内等待执行。5.如果任务队列慢,则拒绝请求
分流(读写分离)
解释:读写通过不同数据库完成(mysql通过binlog来同步事务型SQL来实现)
问题:主从复制导致查询的延迟问题。解决:1.写入数据库的同时也写入一份数据到缓存,应用优先从缓存查询数据 。2. 实时性强的业务直接从主库读。
分片(分库分表)
解释:数据量很大导致索引都很大时,通过分片来解决
垂直拆分:不同业务的数据放不同服务器
水平拆分:根据拆分规则来把一张表数据分到多个服务器(如: 对id进行hash,再对其取余来判断放那个服务器)
带来的问题:
如何定位数据在哪个表:解决:垂直拆分根据不同业务查找,水平拆分通过定义拆分规则主键找,其他字段要建一个其他字段和ID的映射表。
Join查询问题:解决:1.数据冗余,需要链表查询的数据冗余到其他表。2. 代码筛选,先把多个表数据查出来再筛选需要的
数据分页问题。解决:1.通过中间件。2.冗余一份全量数据到Elasticsearch中,通过Elasticsearch 查询分页
无法使用数据库的自增长id。解决:1.使用redis自增,但依赖Redis。2.使用uuid,不依赖任何组件,但它有32 个 16 进制数字组成,比较占空间,不利于索引。
无法直接统计数据量count。解决:通过新建一张表统计或者放到缓存中
分布式事务问题。解决:Spring的JTA、阿里开源的seata
使用nosql
redis:缓存热点数据(存在问题见redis篇)
MongoDB:大量文档型数据的查询
Elasticsearch:全文数据的搜索
核心日志(WAL)
binlog
binlog 是server层的日志,用于恢复和同步数据,但不支持崩溃恢复。(三种记录形式:记录改变的行,记录sql语句,或者混合模式)写入策略为追加。
redolog
redo log是引擎层(innodb)的日志,物理日志,记录的是在数据页上做了什么修改,所以支持崩溃恢复。写入策略是循环写
undolog
undolog属于引擎层(innodb)的日志,记录数据的历史版本,用于事务失败回滚和MVCC版本控制
日志生成顺序与数据恢复
一条语句执行流程
查询语句:1.通过连接器处理客户端连接和授权认证等 2.mysql8.0前先会去缓存区找。没有就先进行词法分析,语法分析,优化sql语句。3. 执行器调用引擎接口,返回执行结果(从磁盘读取)。
更新语句:相对查询语句,1. 在读到数据后记录undolog日志.2. 修改内存数据,然后记录redolog(prepare状态),然后记录binlog,3. 最后提交数据,同时记录redolog(commit状态)
执行顺序(sql解析步骤)
先有表(from ,join ,on)然后过滤(where),然后分组(group by ,having)然后选择显示字段和去重(select distinct),然后排序(order by),最后分页(limit)
redolog为什么需要两阶段提交
redo log日志在事务提交后会持久化到磁盘,如果先写redolog再写binlog,如果一条语句在redolog后崩溃,此时本机有数据,但由于未写binlog,所以从节点会少一条数据,会造成主从不一致。
如果先写binlog再写redolog,如果一条语句写binlog之后崩溃了,事务未提交本机无数据,且因为本机未写入redolog,所以本机数据不能回复。但从服务器可能根据同步的binlog日志已经进行数据修改,从而造成主从不一致。
所以引出两阶段提交:在写binlog前先写一次redolog(prepare状态,此时事务未提交),这样如果是在binlog之后崩溃,从服务器有数据,本机也可以根据redolog重做数据,保证主从数据一致性。
数据库崩溃恢复:
redolog和binlog都无记录,未修改不操作
redolog为prepare状态,binlog无记录,通过undolog回滚
redolog为prepare状态,binlog有记录。根据redo log对数据进行重做(相当于提交事务)。(这里不回滚是因为binlog日志可能已经同步到从服务器了,所以回滚可能导致主从数据不一致)
redolog为commit状态,binlog有记录。正常完成的事务,不需要恢复。
查询实践
sql分类
数据定义语言DDL
用于创建数据库的各种对象(表,视图,索引等)
数据查询语言DQL
对表的查询操作(select)- 位置已排序
数据操纵语言DML
对表的增删改操作
数据控制语言DCL(用于定义访问权限和安全级别)
用于定义访问权限和安全级别
drop,truncate,delete区别
drop和truncate属于DDL语言,对表操作不可回滚。drop会直接删除表内容和表结构,truncate只删除表所有内容
delete属于DML语言,可以回滚,可删除表中部分数据
速度:drop>truncate>delete
对表的查询操作(select)
去重查询distinct
例子:select distinct sal from emp;
连接查询join(笛卡尔积)
内连接
select * from a inner join b on a.s=b.s;//只显示符合条件的内容( inner join 可以省略用逗号代替,然后on换成where)
外连接
左连接查询(left outer join … on ):查询结果参照左表,左边全显示,右表符合条件显示,不符合条件用null填充。
右连接查询(right outer join … on)
原理
简单的嵌套循环连接:双层for 循环,内外层数据一一比较。(nm次)
索引嵌套循环连接:根据内层表的索引去找,减少了循环匹配次数(n*索引高度 次)
缓存块嵌套循环连接:一次性缓存外层表的多条数据到join buffer中,再进行比较,减少IO 次数
mysql中join先使用索引嵌套循环连接,不行再使用缓存块嵌套循环连接
条件查询where
一些关键字:in();between…and…;is null 等等(注意:字符和数字的类型转换:如果=两边类型不同,会把字符转为数字。非数字字符都会转为0,数字字符转换为对应数字。)
模糊查询like
‘_’ 表示任意一个字符,‘%‘表示任意多个字符。
分组查询group by
having对查询结果进行过滤。
条件过滤Having
过滤分组后的信息,条件和where类似,只是位置不同
排序查询order by:
介绍
降序desc(默认s升序asc)
先把查询的的结果方sortbuffer中,然后根据字段排序后将数据返回给客户端。(如果sortbuffer空间不足可以分割数据到多个临时文件,采用归并排序合并再返回客户端,磁盘操作较内存慢很多,所以也可以先获取必要字段(排序字段和id)到sortbuffer中,排序后再根据id查出其他字段,最后返回客户端,具体步骤如下)
原理
1. 把查询出的数据先放到sort buffer中(只放必要字段,如排序字段和id)。
2.根据排序好的字段根据id获取需要的其他数据。
3.返回给客户端(注意:sort buffer在内存中,如果数据超过sortbuffer会把数据拆分到多个临时文件中排序再合并返回给客户端,排序算法为归并排序)
分页查询limit
limit 0,5;//0表示起始行,5表示共读取多少行
查询结果拼接
union
注意事项
IFNULL(a,b):若a为null 返回b,否则返回a
聚合函数:count();avg(列名);sum(列名);max(列名);min(列名)//分别为计算指定列的不为null行数;平均值;和;最大值;最小值;例子:SELECT AVG(column_name) FROM table_name
MD5加密,AES加密(因为MD5加密不可逆,所以只适合不逆转的加密,比如密码。像资料需要回显的可以使用AES加密)
查询姓张 且名字不同 人的个数:COUNT(DISTINCT a.t_name)
要考虑连接时为null的情况,选择左连接或右连接。
能同时得到就用连接,不能同时得到就用嵌套(当多个表连接时,效率不如嵌套)
使用in时判断是否在集合里时,先把集合里重复的去掉提高效率。
条件判断语句:select case when 条件 then … else… end
逻辑(行转列):先分组后,语句MAX(case WHEN a.c_id=‘01’ THEN a.s_score ELSE NULL END)语文 含义:分组后同学的成绩一条条判断,这条成绩可能为语文数学或英语,如第一条判断,如果不为语文就为null,所以最后每个同学每科会有多个成绩(一个真正成绩,还有多个null),所以前面取max。(还可以通过把每列查出来,然后通过连接拼起来)
表中的中文列不能使用 a.‘语文’,而应该使用a. 语文
(tab上面按键)
avg(a):把a一个个加进去,求和然后除以加进去的个数。所以可以求及格率avg(case when a>60 then 1 else 0 end),解释:大于60为1,把大于60个数相加,再除以加进去的个数,就得到了及格率
取别名最好加一个’’,否则与关键字冲突会报错
in还可以这么用in(2,3):表示是否在2,3中
查询年year(date)curdate()curtime()
datediff([参数],日期1,日期2)返回日期1-日期2的天数(参数省略的情况下,参数可以为month:返回间隔的月,注:低版本参数不能使用)
窗口函数(获得排序值)
row_number:相同值排序也不重复90 ,89,89,88 对应1,2,3,4;
rank():跳跃式排序(值相同排序相同)90 ,89,89,88 对应1,2,2,4
dese_rank():连续式排序(值相同排序相同)90 ,89,89,88 对应1,2,2,3
例子:例子:rank() over([partition by 列名] order by 列名)(partition by 是根据什么分组,组内再进行order by,partition by可以省略就是所有数据为一组)
mysql高级使用
游标
作用:游标能从结果集中每次提取一条记录,类似数组的索引,用于对结果集的遍历,以便进行相关操作。
存储函数
作用:封装一系列SQL语句,简化调用。如果只需要返回一个值,就使用函数。
存储过程
一组为了完成特定功能的SQL 语句集,如果需要返回多个值和不返回值,就使用存储过程;
触发器
作用:当对表进行增删改等操作时,会自动触发
事件
可以理解为事件触发器,周期性触发,事件调度器可以精确到每秒钟执行一个任务
视图
虚表,查询语句执行的结果,不存储具体的数据。会随基本表改变而改变。作用:1.简化操作。2.可以通过隐藏某些行达到控制权限的作用。//例子: create view 视图名 as 查询语句