事务:事务是并发控制的基本单元,事务是一个操作序列,要么都执行,要么都不执行,他是一个不可分割的工作单位,事务是维护数据库一致性的单位。在MySQL中,事务是在引擎层面实现的,只有使用innoDB引擎的数据库或表才支持事务。
脏读(dirty read)
、不可重复读(non-repeatable read)
、幻读(phantom read)
的情况,为了解决这些并发问题,提出了隔离性的概念。)数据库的大并发要考虑锁和锁的性能问题,加锁是为了实现并发控制。数据库是一个多用户资源,若对并发控制不加控制会读取和存储不正确的数据,破坏数据的一致性(脏读,不可重复读,幻读等)可能会产生死锁。
锁机制保证在一个事务释放锁之前其他事务不可以进行修改。
锁:行级锁,表级锁,悲观锁,乐观锁
悲观锁:事务每次操作之前假设有其他事务会修改需访问的数据,会要求上锁。
乐观锁:事务每次操作之前假设没有其他事务会修改需访问的数据,不会要求上锁。
共享锁:对某一资源加共享锁,自身可以读该资源,其他人也可以读该资源
共享锁(S锁):如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。
排他锁(X锁):如果事务T对数据A加上排他锁后,则其他事务不能再对A加任何类型的封锁。获准排他锁的事务既能读数据,又能修改数据。
共享锁下其它用户可以并发读取,查询数据。但不能修改,增加,删除数据。资源共享。
Innodb引擎:提供了对数据库ACID事务的支持,并且实现了sql标准的四种隔离级别,事务安全的,支持行级锁,不支持全文索引。
MyISAM引擎:MySQL的默认引擎,没有提供对数据库事务的支持,非事务安全的,锁的粒度是表级的,支持全文索引类型,相对简单性能优。
总结:
MYISAM管理非事务表,提供高速存储和检索,以及全文搜索能力,如果在应用中执行大量的select操作,应选择MYISAM引擎
Innodb用于事务处理,具有ACID事务支持等特性,如果在应用中执行大量的insert和update操作,应选择innodb引擎。
这四个隔离级别可以解决脏读、不可重复读、幻读这三类问题。总结如下:
事务隔离界别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | 允许 | 允许 | 允许 |
读已提交 | 不允许 | 允许 | 允许 |
可重复读 | 不允许 | 不允许 | 允许 |
串行化 | 不允许 | 不允许 | 不允许 |
其中隔离界别由低到高是:读未提交<读已提交<可重复读<串行化
隔离级别越高,越能保证数据的完整性和一致性,但是对并发的性能影响越大。大多数数据库的默认级别是读已提交(Read Committed)
,比如Sql Server、Oracle,但是MySQL的默认隔离级别是可重复读(repeatable-read)
。
通过一定的规则将一个数据集划分成若干个小区域,然后针对若干个小区域进行数据处理。
例:分别计算男女性用户平均年龄:
select 性别,avg(年龄) as average from 表名 group by 性别
第一范式:只要是关系型数据库的表,都满足第一范式。
性质:第一范式的数据表中的所有字段都是单一属性,不可分割。
第二范式:不可使用组合键,确保唯一主键。
第三范式:要求数据表中不存在非关键字段对任一候选关键字段的传递函数依赖,表分开。
在MySQL5.5版本之前,复制都是异步复制。该复制经常遇到的问题是:因为binlog日志是推送的,所有主库和从库之间存在一定的延迟。这样就会造成很多问题,比如主库因为磁盘损坏等故障突然崩掉,导致binlog日志不存在,同时因为延迟binlog还没有推送到从库,从库也就会丢失很多被主库提交的事务,从而造成主从不一致。
解决如上的问题,MySQL5.5版本之后引入了半同步复制机制。
异步复制:主库写入一个事务commit提交并执行完之后将日志记录到binlog,将结果反馈给客户端,最后将日志传输到从库。
半同步复制:主库写入一个事务commit提交并执行完之后,并不直接将请求反馈给前端应用用户,而是等待从库也接收到binlog日志并成功写入中继日志后,主库才返回commit操作成功给客户端。半同步复制保障了事务执行后至少有两份日志记录,一份在主库的binlog上,另一份至少在从库的中继日志Relay log上,这样就极大的保证了数据的一致性。
同步复制:指的是客户端连接到MySQL主服务器写入一段数据,MySQL主服务器同步给MySQL从服务器需要等待从服务器发出同步完成的响应才返回客户端OK,这其中等待同步的过程是阻塞的,如果有N太从服务器,效率极低。
异步复制:指的是客户端连接到MySQL主服务器写入一段数据,MySQL主服务器将写入的数据发送给MySQL从服务器,然后直接返回客户端OK,可能从服务器的数据会和主服务器不一致。
半同步复制:指的是客户端连接到MySQL主服务器写入一段数据,MySQL主服务器只将数据同步复制给其中一台从服务器,半同步复制给其他的从服务器,来达到其中一台从服务器完全同步的效果。
MHA目的在于维持master库的高可用性,最大特点是可以修复多个slave之间的差异日志,最终使所有的slave保持一致,然后从中选择一个新的充当新的master,并使其他的slave指向它。
以上知识点来源于https://blog.csdn.net/lyfqyr/article/details/83351594?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159732754819725247621911%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=159732754819725247621911&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_click~default-3-83351594.first_rank_ecpm_v3_pc_rank_v2&utm_term=%E6%95%B0%E6%8D%AE%E5%BA%93%E9%9D%A2%E8%AF%95%E9%A2%98&spm=1018.2118.3001.4187#commentBox
非关系型数据库称为NoSQL
,也就是Not only SQL,不仅仅是SQL。非关系型数据库不需要写一些复杂的SQL语句,其内部存储方式是以key-value
的形式存在,可以把它想象成电话本的形式,每个人名(key)对应电话(value)。常见的非关系型数据库主要有Hbase、Redis、MongoDB等。非关系型数据库不需要经过SQL的重重解析,所以性能很高;非关系型数据库的可扩展性比较强,数据之间没有耦合性,遇见需要新加字段的需求,就直接增加一个key-value
键值对即可。
关系型数据库以表格
的形式存在,以行和列
的形式存取数据,关系型数据库这一系列的行和列被称为表,无数张表组成了数据库
,常见的关系型数据库有Oracle、DB2、Microsoft SQL Server、MySQL等。关系型数据库能够支持复杂的SQL查询,能够体现出数据之间、表之间的关联关系;关系型数据库也支持事务,便于提交或者回滚。
它们之间的劣势都是基于对方的优势来满足的
MySQL常见的存储引擎,可以使用
SHOW ENGINES
命令,来列出所有的存储引擎
可以看到,InnoDB是MySQL默认支持的存储引擎,支持事务、行级锁定和外键。
在5.1版本之前,MyISAM是MySQL的默认存储引擎,MyISAM并发性比较差,使用的场景比较少,主要特点是
.frm(存储表定义)
、.MYD(MYData,存储数据)
、MYI(MyIndex,存储索引)
。这里需要特别注意的是MyISAM值缓存索引文件,并不缓存数据文件。全局索引(Full-Text)
、B-Tree索引
、R-Tree索引
这道题应该从MySQL架构来理解,我们可以MySQL拆解成几个零件,如下图所示
大致上来说,MySQL可以分为Server层和存储引擎层。
Serer层包括连接器、查询缓存、分析器、优化器、执行器,包括大多数MySQL中的核心功能,所有跨存储引擎的功能也在这一层实现,包括存储过程、触发器、视图等。
存储引擎层包括MySQL常见的存储引擎,包括MyISAM、InnoDB和Memory等,最常用的是InnoDB,也是现在MySQL的默认存储引擎。存储引擎也可以在创建表的时候手动指定,比如下面
CREATE TABLE t (i int) ENGINE = <Storage Engine>;
然后我们就可以探讨MySQL的执行过程了
首先需要在MySQL客户端登录才能使用,所以需要一个连接器来连接用户和MySQL数据库,我们一般是使用
mysql -u 用户名 -p 密码
来进行MySQL登陆,和服务器建立连接。在完成TCP握手后,连接器会根据你输入的用户名和密码验证你的登陆身份。如果用户名或者密码错误,MySQL就会提示Access denied for user,来结束执行。如果登陆成功后,MySQL会根据权限表中的记录来判定你的权限。
连接完成后,你就可以执行SQL语句了,这行逻辑就会来到第二步:查询缓存。
MySQL在得到一个执行请求后,会首先去查询缓存中查找,是否执行过这条SQL语句,之前执行过的语句以及结果会以key-value对的形式,被直接放在内存中。key是查询语句,value是查询结果。如果通过key能够找到这条SQL语句,就直接返回SQL的执行结果。
如果语句不在查询缓存中,就会继续后面的执行阶段。执行完成后,执行结果就会被放入查询缓存中。可以看到,如果查询命中缓存,MySQL不需要执行后面的复杂操作,就可以直接返回结果,效率会很高。
为什么呢?因为只要在MySQL中对某一张表执行了更新操作,那么所有的查询缓存就会失效,对于更新频繁的数据库来说,查询缓存的命中率很低。
如果没有命中查询,就开始执行真正的SQL语句。
经过分析器的词法分析和语法分析后,你这条SQL就合法了,MySQL就知道你要做什么了。但是爱执行前,还需要进行优化器的处理,优化器会判断你使用了哪种索引,使用了何种连接,优化器的作用就是确定效率最高的执行方案。
MySQL通过分析器知道了你的SQL语句是否合法,你想要做什么操作,通过优化器知道了该怎么做效率最高,然后就进入了执行阶段,开始执行这条SQL语句
在执行阶段,MySQL首先会判断你有没有执行这条语句的权限,没有权限的话,就会返回没有权限的错误。如果有权限,就打开表继续执行。打开表的时候,执行器就会根据表的引擎定义,去使用这个引擎提供至此,MySQL对于一条语句的执行过程也就完成了。
我们在编写一个查询语句的时候
select distinct
<select_list>
from
<left_table><join_codition>
where
<where_condition>
group by
<group_by_list>
having
<having_condition>
group by
<order_by_condition>
limit
<limit_number>
首先,对select语句执行查询时,对from关键字两边的表执行连接,会形成笛卡尔积,这时候会产生一个虚表VT1(virtual table)
首先先来解释一下设么事笛卡尔积
现在我们有两个集合A={0,1},B={2,3,4}
那么,集合AB得到的结果就是
A * B = {(0,2)、(1,2)、(0,3)、(1,3)、(0,4)、(1,4)};
B * A = {(2,0)、{2,1}、{3,0}、{3,1}、{4,0}、(4,1)};
上面AB和BA的结果就可以称为一两个集合相乘的笛卡尔积
我们可以得出结论,A集合和B集合相乘,包含了集合A中的元素和集合B中元素之和,也就是A元素的个数B元素的个数
再来解释一下什么是虚表
在MySQL中,有三种类型的表
一种是永久表,永久表就是创建以后用来长期保存数据的表
一种是临时表,临时表也有两类,一种是和永久表一样,只保存临时数据,但是能够长久存在的;还有一种是临时创建的,SQL语句执行完成就会删除。
一种是虚表,虚表其实就是视图,数据可能会来自多张表的执行结果。
然后对FROM连接的结果进行ON筛选,创建VT2,把符合记录的条件存在VT2中。
第三步,如果是OUTER JOIN(left join、right join),那么这一步就将添加外部行,如果是left join就把ON过滤条件的左表添加进来,如果是right join,就把有表添加进来,从而生成新的虚拟表VT3
第四步,是执行WHERE过滤器,对上一步产生的虚拟表引用where筛选,生成虚拟表VT4
where和on的区别
应用
根据group by字句中的列,会对VT4中的记录进行分组操作,产生虚拟机表VT5。如果应用了group by,那么后面的所有步骤都只能得到的VT5的列或者是聚合函数(count、sum、avg等)。
紧跟着group by子句后面的是having,使用having过滤,会把符合条件的放在VT6
第七步才会执行select语句,将VT6中的结果按照select进行筛选,生成VT7
在第八步中,会对VT7生成的记录进行去重操作,生成VT8。事实上如果应用了group by子句那么distinct是多余的,原因同样在于,分组的时候是将列中唯一的值分成一组,同时只为每一组返回一行记录,那么所有的记录都将是不相同的。
应用order by子句。按照order_by_condition排序VT8,此时返回的一个游标,而不是虚拟表。sql是基于集合的理论的,集合不会预先对他的行排序,它只是成员的逻辑集合,成员的顺序是无关紧要的。
什么是临时表?MySQL在执行SQL语句的过程中,通常会临时创建一些存储中间结果集的表,临时表只对当前连接可见,在连接关闭时,临时表会被删除并释放所有表空间。
临时表分为两种:一种是内存临时表,一种是磁盘临时表,什么区别呢?内存临时表使用的是MEMORY存储引擎,而磁盘临时表采用的是MyIsam存储引擎
Memory存储引擎:memory是MySQL中一类特殊的存储引擎,它使用存储在内存中的内容来创建表,饿而且数据全部放在内存中。每个基于MEMORY存储引擎的表实际对应一个磁盘文件。该文件的文件名与表名相同,类型为frm类型。而其数据文件,都是存储在内存中,这样有利于数据的快速处理,提高整个表的效率。MEMORY用到的很少,因为它是把数据存到内存中,如果内存出现异常,就会影响数据。如果重启或者关机,所有数据都会消失。因此,基于MEMORY的表的生命周期很短,一般是一次性的。
MySQL会在下面这几种情况产生临时表
索引是存储在一张表中特定列上的数据结构,索引实在列上创建的。并且,索引是一种数据结构。
在MySQL中,主要有下面这几种索引
MySQL中没有nvarchar数据类型,所以直接比较的是varchar和char的区别
char:表示的是定长的字符串,当你输入小于指定的数目,比如你指定的数目是char(6),当你输入小于6个字符的时候,char会在你最后一个字符后面补空值。当你输入超过指定允许最大长度后,MySQL会报错
varchar:varchar指的是长度为n个字节的可变长度,并且是非unicode的字符数据。n的值是介于1-8000之间的数值。存储大小为实际大小。
Unicode是一种字符编码方案,它为每种语言中的每个字符都设定了统一唯一的二进制编码,以实现跨语言、跨平台进行文本转换、处理的请求
使用char存储定长的数据非常方便、char检索效率高,无论你存储的数据是否到了10个字节,都要去占用10个字节的空间
使用varchar可以存储变长的数据,但存储效率没有char高。
连接的方式主要有三种:外链接、内连接、交叉连接
左外连接:又称为左连接,这种连接方式会显示左表不符合条件的数据行,右边不符合条件的数据行直接显示 NULL
右外连接:也被称为右连接,他与左连接相对,这种连接方式会显示右表不符合条件的数据行,左表不符合条件的数据行直接显示 NULL
SELECT * FROM t_class a, t_Student b WHERE a.classid = b.classid
或者不用CROSS JOIN,直接用FROM也能表示交叉连接的效果
SELECT * FROM t_class a,t_student b WHERE a.classid = b.classid
如果表中字段比较多,不适宜用交叉连接,交叉连接的效率比较差。
(select colum1,colum2...columN from tableA ) union (select colum1,colum2...columN from tableB )
或
(select colum1,colum2...columN from tableA ) union all (select colum1,colum2...columN from tableB );
使用union和union all的注意事项
通过union连接和SQL分别单独取出的列数必须相同
使用union时,多个相等的行将会被合并,由于合并比较耗时,一般不直接使用union进行合并,而是通常采用union all进行合并
水平分割:通过建立结构相同的几张表分别存储数据
垂直分割:将经常一起使用的字段放在一个单独的表中,分割后的表记录之间是一一对应关系
以上知识点来自:https://blog.csdn.net/qq_36894974/article/details/105594307#commentBox