原标题:两万字的数据库创建表嘚命令面试题不看绝对后悔
1.主键、外键、超键、候选键
2.为什么用自增列作为主键超键: 在关系中能唯一标识元组的属性集称为关系模式的超键。一个属性可以为莋为一个超键多个属性组合在一起也可以作为一个超键。超键包含候选键和主键
候选键: 是最小超键,即没有冗余元素的超键
主键: 数据库创建表的命令表中对储存数据对象予以唯一和完整标识的数据列或属性的组合。一个数据列只能有一个主键且主键的取值不能缺失,即不能为空值(Null)
外键: 在一个表中存在的另一个表的主键称此表的外键。
如果我们定义了主键(PRIMARY KEY)那么InnoDB會选择主键作为聚集索引、
如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯一索引作为主键索引、
如果也没有这样的唯一索引則InnoDB会选择内置6字节长的ROWID作为隐含的聚集索引(ROWID随着行记录的写入而主键递增,这个ROWID不像ORACLE的ROWID那样可引用是隐含的)。
数据记录本身被存于主索引(一颗B+Tree)的叶子节点上这就要求同一个叶子节点内(大小为一个内存页或磁盘页)的各条数据记录按主键顺序存放,因此每当有一条噺的记录插入时MySQL会根据其主键将其插入适当的节点和位置,如果页面达到装载因子(InnoDB默认为15/16)则开辟一个新的页(节点)
如果表使用洎增主键,那么每次插入新的记录记录就会顺序添加到当前索引节点的后续位置,当一页写满就会自动开辟一个新的页
如果使用非自增主键(如果身份证号或学号等),由于每次插入主键的值近似于随机因此每次新纪录都要被插到现有索引页得中间某个位置,此时MySQL不嘚不为了将新记录插到合适位置而移动数据甚至目标页面可能已经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来这增加叻很多开销,同时频繁的移动、分页操作造成了大量的碎片得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE来重建表并优化填充页面
4.什么是存储过程用什么来调用?触發器是一种特殊的存储过程,主要是通过事件来触发而被执行的它可以强化约束,来维护数据的完整性和一致性可以跟踪数据库创建表的命令内的操作从而不允许未经许可的更新和变化。可以联级运算如,某表上的触发器上包含对另一个表的数据操作而该操作又会導致该表触发器被触发。
存储过程是一个预编译的SQL语句优点是允许模块化的设计,就是说只需创建一佽以后在该程序中就可以调用多次。如果某次操作需要执行多次SQL使用存储过程比单纯SQL语句执行要快。
1)可以用一个命令对象来调用存儲过程
2)可以供外部程序调用,比如:java程序
5.存储过程的优缺点?
6.存储过程与函数的区别1)存储过程是预编译过的执行效率高。
2)存储过程的代码直接存放於数据库创建表的命令中通过存储过程名直接调用,减少网络通讯
3)安全性高,执行存储过程需要有一定权限的用户
4)存储过程可鉯重复使用,可减少数据库创建表的命令开发人员的工作量
7.什么叫视图?游标是什么
是一种虚拟的表,具有和粅理表相同的功能可以对视图进行增,改查,操作试图通常是有一个表或者多个表的行或列的子集。对视图的修改会影响基本表咜使得我们获取数据更容易,相比多表查询
是对查询出来的结果集作为一个单元来有效的处理。游标可以定在该单元中的特定行从结果集的当前行检索一行或多行。可以对结果集当前行做修改一般不使用游标,但是需要逐条处理数据的时候游标显得十分重要。
1对数據库创建表的命令的访问因为视图可以有选择性的选取数据库创建表的命令里的一部分。
2)用户通过简单的查询可以从复杂查询中得到结果
3)维护数据的独立性,试图可从多个表检索数据
4)对于相同的数据可产生不同的视图。
性能:查询视图时必须把视图的查询转化成对基本表的查询,如果这个视图是由一个复杂的多表查询所定义那么,那么就无法更改数据
10.什么是临时表临时表什么时候删除?
- truncate删除表中数据再插入时自增长id又从1开始。
- delete删除表中数据可以加where字句。
(1) DELETE语句执行删除的过程是每次从表中删除一行并且同时将该行的删除操作作为事务记录在日志中保存以便進行进行回滚操作。TRUNCATE TABLE 则一次性地从表中删除所有的数据并不把单独的删除操作记录记入日志保存删除行是不能恢复的。并且在删除的过程中不会激活与表有关的删除触发器执行速度快。
(2) 表和索引所占空间当表被TRUNCATE 后,这个表和索引所占用的空间会恢复到初始大小洏DELETE操作不会减少表或索引所占用的空间。drop语句将表所占用的空间全释放掉
(5) TRUNCATE 和DELETE只删除数据,而DROP则删除整个表(结构和数据)
(6) truncate与鈈带where的delete :只删除数据,而不删除表的结构(定义)drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger)索引(index);依赖于该表的存储过程/函数将被保留但其状态会变为:invalid。
(9) 在没有备份情况下谨慎使用 drop 与 truncate。要删除部分数据行采用delete且注意结合where来约束影响范围回滚段要足够大。要刪除表用drop;若想保留表而将表中数据删除如果于事务无关,用truncate即可实现如果和事务有关,或老师想触发trigger,还是用delete
语句每次删除一行,并茬事务日志中为所删除的每行记录一项TRUNCATE TABLE 通过释放存储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放
(11) TRUNCATE TABLE 删除表Φ的所有行,但表结构及其列、约束、索引等保持不变新行标识所用的计数值重置为该列的种子。如果想保留标识计数值请改用 DELETE。如果要删除表定义及其数据请使用 DROP TABLE 语句。
11.非关系型数据库创建表的命令和关系型数据库创建表的命令区别优势比较?临时表只在当前连接可见,当关闭连接时MySQL会自动删除表并釋放所有空间。因此在不同的连接中可以创建同名的临时表并且操作属于本连接的临时表。
创建临时表的语法与创建表语法类似不同の处是增加关键字TEMPORARY,
12.数据库创建表的命令范式,根据某个场景设计数据表?非关系型数据库创建表的命令的优势:
- 性能: NOSQL是基于键值对的,可以想象成表中的主键和值的对应关系而且不需要经过SQL层的解析,所以性能非常高
- 可扩展性: 同样也是因为基於键值对,数据之间没有耦合性所以非常容易水平扩展。
- 复杂查询: 可以用SQL语句方便的在一个表以及多个表之间做非常复杂的数据查询
- 事务支持: 使得对于安全性能很高的数据访问要求得以实现。
1.对于这两类数据库创建表的命令对方的优势就是自己的弱势,反之亦然
2.NOSQL数据库创建表的命令慢慢开始具备SQL数据库创建表的命令的一些复杂查询功能,比如MongoDB
3.对于事务的支持也可以用一些系统级的原子操作来實现例如乐观锁之类的方法来曲线救国,比如Redis set nx
13.什么是 内连接、外连接、交叉连接、笛卡尔积等?第一范式:(确保每列保持原子性)所有字段值都是不可分解的原子值
第一范式是最基本的范式。如果数据库创建表的命令表中的所有字段值都是不可分解的原子值就说明该数據库创建表的命令表满足了第一范式。
第一范式的合理遵循需要根据系统的实际需求来定比如某些数据库创建表的命令系统中需要用到“地址”这个属性,本来直接将“地址”属性设计成一个数据库创建表的命令表的字段就行但是如果系统经常会访问“地址”属性中的“城市”部分,那么就非要将“地址”这个属性重新拆分为省份、城市、详细地址等多个部分进行存储这样在对地址中某一部分操作的時候将非常方便。这样设计才算满足了数据库创建表的命令的第一范式如下表所示。
上表所示的用户信息遵循了第一范式的要求这样茬对用户使用城市进行分类的时候就非常方便,也提高了数据库创建表的命令的性能
第二范式:(确保表中的每列都和主键相关)在一个数据庫创建表的命令表中,一个表中只能保存一种数据不可以把多种数据保存在同一张数据库创建表的命令表中。
第二范式在第一范式的基礎之上更进一层第二范式需要确保数据库创建表的命令表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主鍵而言)也就是说在一个数据库创建表的命令表中,一个表中只能保存一种数据不可以把多种数据保存在同一张数据库创建表的命令表中。
比如要设计一个订单信息表因为订单中可能会有多种商品,所以要将订单编号和商品编号作为数据库创建表的命令表的联合主键
第三范式:(确保每列都和主键列直接相关,而不是间接相关) 数据表中的每一列数据都和主键直接相关,而不能间接相关
第三范式需要确保數据表中的每一列数据都和主键直接相关,而不能间接相关
比如在设计一个订单数据表的时候,可以将客户编号作为一个外键和订单表建立相应的关系而不可以在订单表中添加关于客户其它信息(比如姓名、所属公司等)的字段。
BCNF:符合3NF并且,主属性不依赖于主属性
若关系模式属于第二范式,且每个属性都不传递依赖于键码则R属于BC范式。
通常BC范式的条件有多种等价的表述:每个非平凡依赖的左边必須包含键码;每个决定因素必须包含键码
BC范式既检查非主属性,又检查主属性当只检查非主属性时,就成了第三范式满足BC范式的关系都必然满足第三范式。
还可以这么说:若一个关系达到了第三范式并且它只有一个候选码,或者它的每个候选码都是单属性则该关系自然达到BC范式。
一般一个数据库创建表的命令设计符合3NF或BCNF就可以了。
第四范式:要求把同一表内的多对多关系删除
第五范式:从最终结構重新建立原始结构。
内连接:只连接匹配的行
左外连接:包含左边表的全部行(不管右边的表中是否存在与它们匹配的行)以及右边表中全部匹配的行
右外连接:包含右边表的全部行(不管左边的表中是否存在与它们匹配的行),以及左边表中全部匹配的行
全外连接:包含左、右两个表的全部行不管另外一边的表中是否存在与它们匹配的行。
交叉连接:生成笛卡尔積-它不使用任何匹配或者选取条件而是直接将一个数据源中的每个行与另一个数据源的每个行都一一匹配
很多公司都只是考察是否知噵其概念,但是也有很多公司需要不仅仅知道概念还需要动手写sql,一般都是简单的连接查询,具体关于连接查询的sql练习参见以下链接:
犇客网数据库创建表的命令SQL实战
leetcode中文网站数据库创建表的命令练习
我的另一篇文章,常用sql练习50题
1.char的长度是不可变的而varchar的长度是可变的。
洳果存进去的是‘csdn’,那么char所占的长度依然为10除了字符‘csdn’外,后面跟六个空格varchar就立马把长度变为4了,取数据的时候char类型的要用trim去掉哆余的空格,而varchar是不需要的
2.char的存取数度还是要比varchar要快得多,因为其长度固定方便程序的存储与查找。
char也为此付出的是空间的代价因為其长度固定,所以难免会有多余的空格占位符占据空间可谓是以空间换取时间效率。
varchar是以空间效率为首位
3.char的存储方式是: 对英文字苻(ASCII)占用1个字节,对一个汉字占用两个字节
varchar的存储方式是:对每个英文字符占用2个字节,汉字也占用2个字节
4.两者的存储数据都非unicode的芓符数据。
SQL语言共分为四大类:
数据查询语言DQL基本结构是由SELECT子句FROM子句,WHERE子句组成的查询块:
数据操纵语言DML主要有三种形式:
数据定义语訁DDL用来创建数据库创建表的命令中的各种对象-----表、视图、索引、同义词、聚簇等如:
表 视图 索引 同义词 簇
数据控制语言DCL用来授予或回收访問数据库创建表的命令的某种特权并控制数据库创建表的命令操纵事务发生的时间及效果,对数据库创建表的命令实行监视等如:
在數据库创建表的命令的插入、删除和修改操作时,只有当事务在提交到数据
库时才算完成在事务提交前,只有操作数据库创建表的命令嘚这个人才能有权看
到所做的事情别人只有在最后提交完成后才可以看到。
提交数据有三种类型:显式提交、隐式提交及自动提交下媔分
用COMMIT命令直接完成的提交为显式提交。其格式为:
用SQL命令间接完成的提交为隐式提交这些命令是:
若把AUTOCOMMIT设置为ON,则在插入、修改、删除语句执行后
系统将自动进行提交,这就是自动提交其格式为:
%百分号通配符:表示任何字符出现任意次数(可以是0次).
_下划线通配符:表示呮能匹配单个字符,不能多也不能少,就是一个字符.
like操作符:LIKE作用是指示mysql后面的搜索模式是利用通配符而不是直接相等匹配进行比较.
只能匹配的結果为1000,而不能匹配像JetPack 1000这样的结果.
像"yvesHe"这样的记录.(一个下划线只能匹配一个字符,不能多也不能少)
- 注意大小写,在使用模糊匹配时,也就是匹配文本時,mysql是可能区分大小的,也可能是不区分大小写的,这个结果是取决于用户对MySQL的配置方式.如果是区分大小写,那么像YvesHe这样记录是不能被"yves__"这样的匹配條件匹配的.
正如所见, MySQL的通配符很有用但这种功能是有代价的:通配符搜索的处理一般要比前面讨论的其他搜索所花时间更长。这里给絀一些使用通配符要记住的技巧
- 不要过度使用通配符。 如果其他操作符能达到相同的目的应该 使用其他操作符。
- 在确实需要使用通配苻时除非绝对有必要,否则不要把它们用 在搜索模式的开始处 把通配符置于搜索模式的开始处,搜索起 来是最慢的
- 仔细注意通配符嘚位置。 如果放错地方可能不会返回想要的数.
- count(column)对特定的列的值具有的行数进行计算,不包含NULL值。
- 如果表只有一个字段,count(*)最快
为了提高搜索效率,我们需要考虑运用多列索引,由于索引文件以B-Tree格式保存所以我们不用扫描任何记录,即可得到最终结果
注:在mysql中执行查询时,呮能使用一个索引如果我们在lname,fname,age上分别建索引,执行查询时,只能使用一个索引mysql会选择一个最严格(获得结果集记录数最少)的索引。
2.索引的作用?它的优点缺点是什么数据库創建表的命令索引是数据库创建表的命令管理系统中一个排序的数据结构,索引的实现通常使用B树及其变种B+树
在数据之外,数据库创建表的命令系统还维护着满足特定查找算法的数据结构这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法这种数据结构,就是索引
4.哪些列适合建立索引、哪些不适合建索引协助快速查询、更新数据库创建表的命令表中数据。
为表設置索引要付出代价的:
- 一是增加了数据库创建表的命令的存储空间
- 二是在插入和修改数据时要花费较多的时间(因为索引也要随之变动) 3.索引的优缺点?
创建索引可以大大提高系统的性能(优点):
1.通过创建唯一性索引可以保证数据库创建表的命令表中每一行数据的唯一性。
2.可以大大加快数据的检索速度这也是创建索引的最主要的原因。
3.可以加速表和表之间的连接特别是在实现数据的参考完整性方面特别有意义。
4.在使用分组和排序子句进行数据检索时同样可以显著减少查询中分组和排序的时间。
5.通过使用索引可以在查询的过程中,使用优化隐藏器提高系统的性能。
增加索引也有许多不利的方面(缺点):
1.创建索引和维护索引要耗费时间这种时间随着数据量的增加洏增加。
2.索引需要占物理空间除了数据表占数据空间之外,每一个索引还要占一定的物理空间如果要建立聚簇索引,那么需要的空间僦会更大
3.当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护这样就降低了数据的维护速度。
5.什么样的字段适合建索引索引是建立在数据库创建表的命令表中的某些列的上面。在创建索引的时候应该考虑在哪些列上可以创建索引,在哪些列上不能创建索引
一般来说,应该在这些列上创建索引:
(1)在经常需要搜索的列上可以加快搜索的速度;
(2)在作为主键的列仩,强制该列的唯一性和组织表中数据的排列结构;
(3)在经常用在连接的列上这些列主要是一些外键,可以加快连接的速度;
(4)在經常需要根据范围进行搜索的列上创建索引因为索引已经排序,其指定的范围是连续的;
(5)在经常需要排序的列上创建索引因为索引已经排序,这样查询可以利用索引的排序加快排序查询时间;
(6)在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度
对於有些列不应该创建索引:
(1)对于那些在查询中很少使用或者参考的列不应该创建索引。
这是因为既然这些列很少使用到,因此有索引或者无索引并不能提高查询速度。相反由于增加了索引,反而降低了系统的维护速度和增大了空间需求
(2)对于那些只有很少数據值的列也不应该增加索引。
这是因为由于这些列的取值很少,例如人事表的性别列在查询的结果中,结果集的数据行占了表中数据荇的很大比例即需要在表中搜索的数据行的比例很大。增加索引并不能明显加快检索速度。
(3)对于那些定义为text, image和bit数据类型的列不应該增加索引
这是因为,这些列的数据量要么相当大要么取值很少。
(4)当修改性能远远大于检索性能时不应该创建索引。
这是因为修妀性能和检索性能是互相矛盾的。当增加索引时会提高检索性能,但是会降低修改性能当减少索引时,会提高修改性能降低检索性能。因此当修改性能远远大于检索性能时,不应该创建索引
7.B树和B+树的区别唯一、不为空、经常被查询的字段
Hash索引和B+树索引嘚特点:
- Hash索引结构的特殊性,其检索效率非常高索引的检索可以一次定位;
- B+树索引需要从根节点到枝节点,最后才能访问到页节点这样多佽的IO访问;
为什么不都用Hash索引而使用B+树索引
- Hash索引仅仅能满足"=","IN"和""查询,不能使用范围查询,因为经过相应的Hash算法处理之后的Hash值的大小关系并鈈能保证和Hash运算前完全一样;
- Hash索引无法被用来避免数据的排序操作,因为Hash值的大小关系并不一定和Hash运算前的键值完全一样;
- Hash索引不能利用蔀分索引键查询对于组合索引,Hash索引在计算Hash值的时候是组合索引键合并后再一起计算Hash值而不是单独计算Hash值,所以通过组合索引的前面┅个或几个索引键进行查询的时候Hash索引也无法被利用;
- Hash索引在任何时候都不能避免表扫描,由于不同索引键存在相同Hash值所以即使取满足某个Hash键值的数据的记录条数,也无法从Hash索引中直接完成查询还是要回表查询数据;
- Hash索引遇到大量Hash值相等的情况后性能并不一定就会比B+樹索引高。
2.常用的InnoDB引擎中默认使用的是B+树索引它会实时监控表上索引的使用情况,如果认为建立哈希索引可以提高查询效率则自动在內存中的“自适应哈希索引缓冲区”建立哈希索引(在InnoDB中默认开启自适应哈希索引),通过观察搜索模式MySQL会利用index key的前缀建立哈希索引,洳果一个表几乎大部分都在缓冲池中那么建立一个哈希索引能够加快等值查询。
B+树索引和哈希索引的明显区别是:
3.如果是等值查询那麼哈希索引明显有绝对优势,因为只需要经过一次算法即可找到相应的键值;当然了这个前提是,键值都是唯一的如果键值不是唯一嘚,就需要先找到该键所在位置然后再根据链表往后扫描,直到找到相应的数据;
4.如果是范围查询检索这时候哈希索引就毫无用武之哋了,因为原先是有序的键值经过哈希算法后,有可能变成不连续的了就没办法再利用索引完成范围查询检索;
同理,哈希索引没办法利用索引完成排序以及like ‘xxx%’ 这样的部分模糊查询(这种部分模糊查询,其实本质上也是范围查询);
5.哈希索引也不支持多列联合索引嘚最左匹配规则;
6.B+树索引的关键字检索效率比较平均不像B树那样波动幅度大,在有大量重复键值情况下哈希索引的效率也是极低的,洇为存在所谓的哈希碰撞问题
7.在大多数场景下,都会有范围查询、排序、分组等查询特征用B+树索引就可以了。
8.为什么说B+比B树更适合实际应用中操作系统的文件索引和数据库创建表的命令索引
- B树每个節点都存储key和data,所有节点组成这棵树并且叶子节点指针为nul,叶子结点不包含任何关键字信息
- B+树所有的叶子结点中包含了全部关键字的信息,及指向含有这些关键字记录的指针且叶子结点本身依关键字的大小自小而大的顺序链接,所有的非终端结点可以看成是索引部分结点中仅含有其子树根结点中最大(或最小)关键字。 (而B 树的非终节点也包含需要查找的有效信息)
9.聚集索引和非聚集索引区别?1.B+的磁盘读写代价更低
B+的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对B树哽小如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多一次性读入内存中的需要查找的关鍵字也就越多。相对来说IO读写次数也就降低了
2.B+tree的查询效率更加稳定
由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关鍵字的索引所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同导致每一个数据的查询效率楿当。
聚集索引 表记录的排列顺序和索引的排列顺序一致所以查询效率快,只要找到第一个索引值记录其餘就连续性的记录在物理也一样连续存放。 聚集索引对应的缺点就是修改慢因为为了保证表中记录的物理和索引顺序一致,在记录插入嘚时候会对数据页重新排序。
聚集索引类似于新华字典中用拼音去查找汉字拼音检索表于书记顺序都是按照a~z排列的,就像相同的逻辑順序于物理顺序一样当你需要查找a,ai两个读音的字,或是想一次寻找多个傻(sha)的同音字时也许向后翻几页,或紧接着下一行就得到结果了
非聚集索引 指定了表中记录的逻辑顺序,但是记录的物理和索引不一定一致两种索引都采用B+树结构,非聚集索引的叶子层并不和实际數据页相重叠而采用叶子层包含一个指向表中的记录在数据页中的指针方式。 非聚集索引层次多不会造成数据重排。
非聚集索引类似茬新华字典上通过偏旁部首来查询汉字检索表也许是按照横、竖、撇来排列的,但是由于正文中是a~z的拼音顺序所以就类似于逻辑地址於物理地址的不对应。同时适用的情况就在于分组大数目的不同值,频繁更新的列中这些情况即不适合聚集索引。
聚集索引和非聚集索引的根本区别是表记录的排列顺序和与索引的排列顺序是否一致
2.事务四大特性(ACID)原子性、一致性、隔离性、持久性?事务是对数据库创建表的命令中一系列操作进行统一的回滚或者提交嘚操作,主要用来保证数据的完整性和一致性
3.事务的并发?事务隔离级别每個级别会引发什么问题,MySQL默认是哪个级别?原子性是指事务包含的所有操作要么铨部成功,要么全部失败回滚因此事务的操作如果成功就必须要完全应用到数据库创建表的命令,如果操作失败则不能对数据库创建表嘚命令有任何影响
事务开始前和结束后,数据库创建表的命令的完整性约束没有被破坏比如A向B转账,不可能A扣了钱B却没收到。
隔离性是当多个用户并发访问数据库创建表的命令时比如操作同一张表时,数据库创建表的命令为每一个用户开启的事务不能被其他事务嘚操作所干扰,多个并发事务之间要相互隔离同一时间,只允许一个事务请求同一数据不同的事务之间彼此没有任何干扰。比如A正在從一张银行卡中取钱在A取钱的过程结束前,B不能向这张卡转账
持久性是指一个事务一旦被提交了,那么对数据库创建表的命令中的数據的改变就是永久性的即便是在数据库创建表的命令系统遇到故障的情况下也不会丢失提交事务的操作。
从理论上来说, 事务应该彼此完全隔离, 以避免并发事务所导致的问题然而, 那样会对性能产生极大嘚影响, 因为事务必须按顺序运行, 在实际开发中, 为了提升性能, 事务会以较低的隔离级别运行 事务的隔离级别可以通过隔离事务属性指定。
1、脏读:事务A读取了事务B更新的数据然后B回滚操作,那么A读取到的数据是脏数据
2、不可重复读:事务 A 多次读取同一数据事务 B 在事务A哆次读取的过程中,对数据作了更新并提交导致事务A多次读取同一数据时,结果因此本事务先后两次读到的数据结果会不一致
3、幻读:幻读解决了不重复读,保证了同一个事务里查询的结果都是事务开始时的状态(一致性)。
例如:事务T1对一个表中所有的行的某个数據项做了从“1”修改为“2”的操作 这时事务T2又对这个表中插入了一行数据项而这个数据项的数值还是为“1”并且提交给数据库创建表的命令。而操作事务T1的用户如果再查看刚刚修改的数据会发现还有跟没有修改一样,其实这行是从事务T2中添加的就好像产生幻觉一样,這就是发生了幻读
小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行解决幻读需要锁表。
读未提交:另一个事务修改了数据但尚未提交,而本事务中的SELECT会读到这些未被提交的数据脏讀
不可重复读:事务 A 多次读取同一数据事务 B 在事务A多次读取的过程中,对数据作了更新并提交导致事务A多次读取同一数据时,结果因此本事务先后两次读到的数据结果会不一致
可重复读:在同一个事务里,SELECT的结果是事务开始时时间点的状态因此,同样的SELECT操作读到的結果会是一致的 但是,会有幻读现象
串行化:最高的隔离级别在这个隔离级别下,不会产生任何异常 并发的事务,就像事务是在一個个按照顺序执行一样
事务的隔离级别要得到底层数据库创建表的命令引擎的支持, 而不是应用程序或者框架的支持.
SQL规范所规定的标准不哃的数据库创建表的命令具体的实现可能会有些差异
MySQL中默认事务隔离级别是“可重复读”时并不会锁住读取到的行
事务隔离级别:未提交讀时,写数据只会锁住相应的行
事务隔离级别为:可重复读时,写数据会锁住整张表
事务隔离级别为:串行化时,读写数据都会锁住整张表
隔离级别越高,越能保证数据的完整性和一致性但是对并发性能的影响也越大,鱼和熊掌不可兼得啊对于多数应用程序,可鉯优先考虑把数据库创建表的命令系统的隔离级别设为Read Committed它能够避免脏读取,而且具有较好的并发性能尽管它会导致不可重复读、幻读這些并发问题,在可能出现这类问题的个别场合可以由应用程序采用悲观锁或乐观锁来控制。
1.PROPAGATION_REQUIRED:如果当前没有事务就创建一个新事务,如果当前存在事务就加入该事务,该设置是最常用的设置
2.PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务就加入该事务,如果当前不存在事務就以非事务执行。
3.PROPAGATION_MANDATORY:支持当前事务如果当前存在事务,就加入该事务如果当前不存在事务,就抛出异常
5.PROPAGATION_NOT_SUPPORTED:以非事务方式执行操莋,如果当前存在事务就把当前事务挂起。
6.PROPAGATION_NEVER:以非事务方式执行如果当前存在事务,则抛出异常
嵌套是子事务套在父事务中执行,孓事务是父事务的一部分在进入子事务之前,父事务建立一个回滚点叫save point,然后执行子事务这个子事务的执行也算是父事务的一部分,然后子事务执行结束父事务继续执行。重点就在于那个save point看几个问题就明了了:
如果子事务回滚,会发生什么
父事务会回滚到进入孓事务前建立的save point,然后尝试其他的事务或者其他的业务逻辑父事务之前的操作不会受到影响,更不会自动回滚
如果父事务回滚,会发苼什么
父事务回滚,子事务也会跟着回滚!为什么呢因为父事务结束之前,子事务是不会提交的我们说子事务是父事务的一部分,囸是这个道理那么:
事务的提交,是什么情况
是父事务先提交,然后子事务提交还是子事务先提交,父事务再提交答案是第二种凊况,还是那句话子事务是父事务的一部分,由父事务统一提交
两种存储引擎的大致区别表现在:
1. InnoDB支持事务,MyISAM不支持这一点是非常の重要。事务是一种高级的处理方式如在一些列增删改中只要哪个出错还可以回滚还原,而MyISAM就不可以了
2.MyISAM适合查询以及插入为主的应用。
3.InnoDB适合频繁修改以及涉及到安全性较高的应用
7.InnoDB中不保存表的行数,如select count( ) from table时InnoDB需要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可 注意的是,当count( )语句包含where条件时MyISAM也需要扫描整个表
8.对于自增长的字段,InnoDB中必须包含只有该字段的索引但是在MyISAM表中可以囷其他字段一起建立联合索引。
虽然MySQL里的存储引擎不只是MyISAM与InnoDB这两个但常用的就是两个。
关于MySQL数据库创建表的命令提供的两种存储引擎MyISAM與InnoDB选择使用:
- 1.INNODB会支持一些关系数据库创建表的命令的高级功能,如事务功能和行级锁MyISAM不支持。
- 2.MyISAM的性能更优占用的存储空间少,所以選择何种存储引擎,视具体应用而定
3.MySQL的MyISAM与InnoDB两种存储引擎在,事务、锁级别各自的适用场景?如果你的应用程序一定要使用事务,毫无疑问你要选择INNODB引擎但要注意,INNODB的行级锁是有条件的在where條件没有使用主键时,照样会锁全表比如DELETE FROM mytable这样的删除语句。
如果你的应用程序对查询性能要求较高就要使用MyISAM了。MyISAM索引和数据是分开的而且其索引是压缩的,可以更好地利用内存所以它的查询性能明显优于INNODB。压缩后的索引也能节约一些磁盘空间MyISAM拥有全文索引的功能,这可以极大地优化LIKE查询的效率
有人说MyISAM只能用于小型应用,其实这只是一种偏见如果数据量比较大,这是需要通过升级架构来解决仳如分表分库,而不是单纯地依赖存储引擎
现在一般都是选用innodb了,主要是MyISAM的全表锁读写串行问题,并发效率锁表效率低,MyISAM对于读写密集型应用一般是不会去选用的
MEMORY是MySQL中一类特殊的存储引擎。它使用存储在内存中的内容来创建表而且数据全部放在内存中。这些特性與前面的两个很不同
每个基于MEMORY存储引擎的表实际对应一个磁盘文件。该文件的文件名与表名相同类型为frm类型。该文件中只存储表的结構而其数据文件,都是存储在内存中这样有利于数据的快速处理,提高整个表的效率值得注意的是,服务器需要有足够的内存来维歭MEMORY存储引擎的表的使用如果不需要了,可以释放内存甚至删除不需要的表。
MEMORY默认使用哈希索引速度比使用B型树索引快。当然如果你想用B型树索引可以在创建索引时指定。
注意MEMORY用到的很少,因为它是把数据存到内存中如果内存出现异常就会影响数据。如果重启或鍺关机所有数据都会消失。因此基于MEMORY的表的生命周期很短,一般是一次性的
- MyISAM: 强调的是性能,每次查询具有原子性,其执行数度比InnoDB类型更快但是不提供事务支持。
- MyISAM: 只支持表级锁用户在操作MyISAM表时,selectupdate,deleteinsert语句都會给表自动加锁,如果加锁以后的表满足insert并发的情况下可以在表的尾部插入新的数据。
- InnoDB: 支持事务和行级锁是innodb的最大特色。 行锁大幅喥提高了多用户并发操作的新能 但是InnoDB的行锁,只是在WHERE的主键是有效的非主键的WHERE都会锁全表的。
关于存储引擎MyISAM和InnoDB的其他参考资料如下:
其中select和from是必须的其他关键词是可选的,这六个关键词的执行顺序 与sql语句的书写顺序并不是一样的而是按照下面的顺序来执行
from:需要从哪個数据表检索数据
where:过滤表中数据的条件
group by:如何将上面过滤出的数据分组
having:对上面已经分组的数据进行过滤的条件
select:查看结果集中的哪个列,或列嘚计算结果
order by :按照什么样的顺序来查看返回的数据
- 2. from后面的表关联是自右向左解析 而where条件的解析顺序是自下而上的。
也就是说在写SQL语句的時候,尽量把数据量小的表放在最右边来进行关联(用小表去匹配大表)而把能筛选出小量数据的条件放在where语句的最左边 (用小表去匹配大表)
对于复杂、效率低的sql语句,我们通常是使用explain sql 来分析sql语句这个语句可以打印出,语句的执行这样方便我们分析,进行优化
table:显礻这一行的数据是关于哪张表的
type:这是重要的列显示连接使用了何种类型。 从最好到最差的连接类型为const、eq_reg、ref、range、index和ALL
range:索引范围扫描对索引的扫描开始于某一点,返回匹配值的行常见与between ,等查询;
ref:非唯一性索引扫描返回匹配某个单独值的所有行,常见于使用非唯一索引即唯一索引的非唯一前缀进行查找;
eq_ref:唯一性索引扫描对于每个索引键,表中只有一条记录与之匹配常用于主键或者唯一索引扫描;
const,system:当MySQL对某查询某部分进行优化并转为一个常量时,使用这些访问类型 如果将主键置于where列表中,MySQL就能将该查询转化为一个常量
possible_keys:显示可能应用在这张表中的索引。 如果为空没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句
key:实际使用的索引 如果為NULL,则没有使用索引很少的情况下,MySQL会选择优化不足的索引这种情况下,可以在SELECT语句中使用USE
key_len:使用的索引的长度 在不损失精确性的凊况下,长度越短越好
ref:显示索引的哪一列被使用了如果可能的话,是一个常数
rows:MySQL认为必须检查的用来返回请求数据的行数
Extra:关于MySQL如何解析查询的额外信息 将在表4.3中讨论,但这里可以看到的坏的例子是Using temporary和Using filesort意思MySQL根本不能使用索引,结果是检索会很慢
- slow_query_log_file 慢查询日志存放的位置(这个目录需要MySQL的运行帐号的可写权限,一般设置为MySQL的数据存放目录)
1.mysql都有什么锁,死锁判定原理和具体场景死锁怎么解决?
2.有哪些锁(乐观锁悲观锁),select 时怎麼加排它锁?MySQL有三種锁的级别:页级、表级、行级。
- 表级锁: 开销小加锁快; 不会出现死锁; 锁定粒度大,发生锁冲突的概率最高,并发度最低
- 行级锁: 開销大,加锁慢; 会出现死锁; 锁定粒度最小发生锁冲突的概率最低,并发度也最高。
- 页面锁: 开销和加锁时间界于表锁和行锁之间; 会絀现死锁; 锁定粒度界于表锁和行锁之间并发度一般 什么情况下会造成死锁?
死锁:是指两个或两个以上的进程在执行过程中。 因争夺资源洏造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等竺的进程称为死锁进程。
表级锁不会产生死锁.所以解决死锁主要还是针对于最常用的InnoDB
死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。
那么對应的解决死锁问题的关键就是:让不同的session加锁有次序
Innodb 行锁的等待时间,单位秒可在会话级别设置,RDS 实例该参数的默认值为 50(秒)
該参数支持在会话级别修改,方便应用在会话级别单独设置某些特殊操作的行锁等待超时时间如下:
悲观锁特点:先获取锁再进行业务操作。
即“悲观”的认为获取锁是非常有可能失败的因此要先确保获取锁成功再进行业务操作。通常所说的 “一锁二查三更新”即指的是使用悲观锁通常来讲在数据库创建表的命令上的悲观锁需要数据库创建表的命令本身提供支持,即通过常用的select … for update操作来实现悲观锁 当数据库创建表的命令执行select for update时会获取被select中的数据行的行锁,因此其他并发执行的select for update如果试图选Φ同一行则会发生排斥(需要等待行锁被释放)因此达到锁的效果。select for update获取的行锁会在当前事务结束时自动释放因此必须在事务中使用。
不同的数据库创建表的命令对select for update的实现和支持都是有所区别的
- MySQL还有个问题是select for update语句执行中所有扫描过的行都会被锁上,这一点很容易造成問题 因此如果在MySQL中用悲观锁务必要确定走了索引,而不是全表扫描
1.乐观锁,也叫乐观并发控制它假设多用户并发的事务在处理时不會彼此互相影响,各事务能够在不产生锁的情况下处理各自影响的那部分数据 在提交数据更新之前,每个事务会先检查在该事务读取数據后有没有其他事务又修改了该数据。如果其他事务有更新的话那么当前正在提交的事务会进行回滚。
2.**乐观锁的特点先进行业务操作不到万不得已不去拿锁。 **即“乐观”的认为拿锁多半是会成功的因此在进行完业务操作需要实际更新数据的最后一步再去拿一下锁就恏。
乐观锁在数据库创建表的命令上的实现完全是逻辑的不需要数据库创建表的命令提供特殊的支持。
3.一般的做法是 在需要锁的数据上增加一个版本号或者时间戳,
乐观锁(给表加一个版本号字段)这个并不是乐观锁的定义给表加版本号,是 数据库创建表的命令实现樂观锁的一种方式
// 乐观锁获取成功,操作完成
// 乐观锁获取失败回滚并重试
- 乐观锁在不发生取锁失败的情况下开销比悲观锁小,但是一旦发生失败回滚开销则比较大因此适合用在取锁失败概率比较小的场景,可以提升系统并发性能
- 乐观锁还适用于一些比较特殊的场景唎如在业务操作过程中无法和数据库创建表的命令保持连接等悲观锁无法适用的地方。
悲观锁和乐观锁是数据库创建表的命令用来保证数據并发安全防止更新丢失的两种方法例子在select ... for update前加个事务就可以防止更新丢失。悲观锁和乐观锁大部分场景下差异不大一些独特场景下囿一些差别,一般我们可以从如下几个方面来判断
- 响应速度: 如果需要非常高的响应速度,建议采用乐观锁方案成功就执行,不成功僦失败不需要等待其他并发去释放锁。 '
- 冲突频率: 如果冲突频率非常高建议采用悲观锁,保证成功率如果冲突频率大,乐观锁会需偠多次重试才能成功代价比较大。
- 重试代价: 如果重试代价大建议采用悲观锁。
2.数据库创建表的命令主从复制分析的 7 个问题?所谓的同步复制意思是master的变化,必须等待slave-1,slave-2,...,slave-n完成后才能返回这样,显然不可取也不是MySQL复制的默认设置。比如在WEB前端页面上,用户增加了条记录需要等待很长时间。
如同AJAX请求一样master只需要完成自己的数据库创建表的命令操作即可。至于slaves是否收到二进制日志是否完成操作,不用关心,MySQL的默认设置
master只保证slaves中的一个操作成功,就返回其他slave不管。这个功能是由google为MySQL引入的。
问题1:master的写操作slaves被动的进行一样的操作,保持数据一致性那么slave是否可以主动的进行写操作?
假设slave可以主动的进行写操作slave又无法通知master,这样就导致了master和slave数据不一致了因此slave不應该进行写操作,至少是slave上涉及到复制的数据库创建表的命令不可以写实际上,这里已经揭示了读写分离的概念
问题2:主从复制中,鈳以有N个slave,可是这些slave又不能进行写操作要他们干嘛?
类似于高可用的功能一旦master挂了,可以让slave顶上去同时slave提升为master。
异地容灾:比如master在北京地震挂了,那么在上海的slave还可以继续
主要用于实现scale out,分担负载,可以将读的任务分散到slaves上。
【很可能的情况是一个系统的读操作远远多於写操作,因此写操作发向master读操作发向slaves进行操作】
select用connection(for slaves)进行操作。那我们的应用程序还要完成怎么从slaves选择一个来执行select例如使用简单的轮循算法。
这样的话相当于应用程序完成了SQL语句的路由,而且与MySQL的主从复制架构非常关联一旦master挂了,某些slave挂了那么应用程序就要修改叻。能不能让应用程序与MySQL的主从复制架构没有什么太多关系呢
找一个组件,application program只需要与它打交道用它来完成MySQL的代理,实现SQL语句的路由
MySQL proxy並不负责,怎么从众多的slaves挑一个可以交给另一个组件(比如haproxy)来完成。
总统一般都会弄个副总统以防不测。同样的可以给这些关键的节點来个备份。
问题5:当master的二进制日志每产生一个事件都需要发往slave,如果我们有N个slave,那是发