数据库存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建、查询、更新和删除数据。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能,使用不同的存储引擎,还可以获得特定的功能。现在许多不同的数据库管理系统都支持多种不同的数据引擎。存储引擎主要有:1.Mylsam,2.InnoDB,3.Memory,4.Archive,5.Federated
InnoDB底层存储结构为B+树,B树的每个节点对应innodb的一个page,page大小是固定的,一般设为16k。其中非叶子节点只有键值,叶子节点包含完成数据
使用场景:
经常更新的表,适合处理多重并发的更新请求
支持事务
可以从灾难中恢复(通过bin-log日志)
外键约束。只有他支持外键
支持自动增加列属性 auto_increment
TokuB底层存储结构为Fractal Tree,Fractal Tree的结构与B+数有些类似,在Fractal Tree中,每一个child指针除了需要指向一个child节点外,还会带有一个Message Buffer,这个Message Buffer是一个FIFO的队列,用来缓存更新操作。
列如,一次插入操作只需要落在某节点的Message Buffer就可以马上返回了,并不需要搜索到叶子节点。这些缓存的更新会在查询时或后台异步合并应用到对应的节点中
TokuDB在线添加索引,不影响读写操作,非常快的写入性能,Fractal -tree在事务实现上有优势。他主要适用于访问频率不高的数据或历史数据归档
MyISAM是Mysql默认的引擎,但是它没有提供对数据库事务的支持,也不支持行级锁和外键,因此当nsert(插入)或update(更新)数据时即写入操作需要锁定整个表,效率便会低一些
Iasm执行读取操作的速度很快了,而且不占用大量的内存和存储资源。在设计之初就预想数据组织成有固定长度的记录,按顺序存储的。
lsam是一种静态索引结构
缺点是它不支持事务处理
memory(也叫heap)堆内存:使用存在内存中的内容来创建表。每个Memory表只实际对应一个磁盘文件。memory类型的表访问非常的快,因为他的数据是放在内存中的,并且默认使用hash索引。但是一旦服务关闭,表中的数据就会丢失掉。memory同时支持散列索引和B树索引,B树索引可以使用部分查询和通配查询的,也可以使用<,>和>=等操作符方便数据挖掘,散列索引相等的比较快但是对于范围的比较慢很多
如何查看mysql提供的所有的存储引擎
mysql>show engines;
mysql常用引擎包括:myisam,innodb,memory(满摸瑞),merge
1.myisam:全表锁,拥有较高的执行速度,不支持事务,不支持外键,并发性能差,占用空间相对较少,对事务完整性没有要求,以select、insert为主的应用基本上可以使用这个引擎
2.innodb:行级锁,提供了具有提交、回滚和奔溃恢复能力的事务安全,支持自动增长列,支持外键约束,并发能力强,占用空间是myisam的2.5倍,处理效率相对会差一些
3.memory:全表锁,存储在内存中,速度快,但是会占用和数据量成正比的内存空间且数据在mysql重启会丢失,默认使用hash索引,捡索效率非常高,但是不适用于精确查找,主要用于那些内容变化不频繁的代码表
4.merge:是一组myisam表的组合
1.innodb支持事务,myisam不支持,对于innodb每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务
2.innodb支持外键,而myisam不支持。对一个包含外键的innodb表转为myisam会失败
3.innodb是聚集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率很高。但是辅助索引需要俩次查询,先查询到主键,然后再通过主键查询到数据库。因此,主键不应该过大,因为主键太大,其他索引也都会很大。而myisam是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的
4.innodb不保存表的具体行数,执行select count(*)from table时需要全表扫描。而myisam用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快
5.innodb不支持全文索引,而myisam支持全文索引,查询效率上myisam要高
索引是帮助mysql高效获取数据的数据结构。常见的查询算法,顺序查找,二分查找,二叉排序树查找,哈希散列法,分块查找,平衡多路搜索树B树(B-tree),索引是对数据库表中一个或多个列的值进行排序的结构,建立索引有助于快速获取信息
你也可以这样理解:索引就是加快检索表中数据的方法。数据的索引类似于书籍的索引。在书籍中,索引允许用户不必翻阅整个书就能迅速的找到所需要的信息。在数据库中,索引也允许数据库程序迅速的找到表中的数据,而不必扫描整个数据库
mysql有四种不同的索引
主键索引(primary),唯一索引(unique),普通索引(index),全文索引(fulltext)
索引并非是越多越好,创建索引也需要耗费资源,一是增加了数据库的存储空间,二是在插入和删除时要花费较多的时间维护索引
索引加快数据库的 检索速度
索引降低了插入,删除,修改等维护任务的速度
唯一索引可以确保每一行数据的唯一性
通过使用索引,可以在查询的过程中使用优化隐藏器,提高系统的性能
索引需要占物理和数据空间
1.选择唯一索引,唯一索引的值是唯一的,可以更快速的通过该索引来确定某条记录
2.为经常需要排序,分组和联合操作的字段建立索引
3.限制索引的数目:
越多的索引,会使更新表变得很浪费时间。尽量使用数据量少的索引
4.为常用作为查询条件的字段建立索引
5.如果索引的值很长,那么查询的速度会受到影响。尽量使用前缀来索引
6.如果索引字段的值很长,最好使用值得前缀来索引
7.删除不再使用或者很少使用的索引
8.最左前缀匹配原则,非常重要的原则
9.尽量的扩展索引,不要新建索引
10.索引列不能参与计算,带函数的查询不参与索引
第一范式:列不可再分
第二范式:行可以唯一区分,主键约束
第三范式:表的非主属性不能依赖与其他表的非主属性 外键约束
且三大范式是一级一级依赖的,第二范式建立在第一范式上,第三范式建立第一第二范式上
第一范式的目标是确保每列的原子性:如果每列都是不可再分的最小数据单元(也称为最小的原子单元),则满足第一范式(1NF)
首先满足第一范式,并且表中非主键列不存在在对主键的部分依赖。第二范式要求每个表只描述一件事情
第三范式定义是,满足第二范式,并且表中的列不存在对非主键列的传递依赖。除了主键订单编号外,顾客姓名依赖与非主键顾客编号
事务(transaction)是作为单个逻辑工作单元执行的一系列操作,这些操作作为一个整体一起向系统提交,要么都执行,要么都不执行。
事务是一个不可分割的工作逻辑单元事务必须具备以下四个属性,简称ACID属性
原子性(atomicity)
事务是一个完整的操作。事务的各步操作是不可分的;要么都执行,要么都不执行
一致性(consistency)
当事务完成时,数据必须处于一致状态
隔离性(isolation)
对数据进行修改的所有并发事务是彼此隔离的,这表明事务必须是独立的,它不应以任何方式依赖于或影响其他事务
永久性(durability)
事务完成后,它对数据库的修改被永久保持,事务日志能够保持事务的永久性
1.查询语句中不要用select *
2.尽量减少子查询,使用关联查询(left join,right join,inner join)替代
3.减少使用in或not in,使用exists,not exists或者关联查询语句替代
4.or的查询尽量用union或者union all替代
5.不要再where字句中使用!=或<>操作符,否则将引擎放弃使用索引进行全表扫描
SQL中的drop,delete,truncate都表示删除,但是三者有一些区别
delete和truncate只删除表的数据不删除表的结构
速度,一般来说drop>truncate>delete
delete语句是dml,这个操作会放到rollbacksegement中,事务提交之后才生效;
如果有相应的trigger,执行的时候将被触发,truncate,drop是ddl,操作立即生效,原数据不放到rollbacksegment中,不能回滚,操作不触发trigger
视图是一种虚拟的表,具有和物理表相同的功能。可以对视图进行增,改,查,操作,试图通常是有一个表或者多个表的行或列的子集。对视图的修改不影响基本表。它使得我们获取数据更容易,相比多表查询
内连接(inner join ):匹配2张表中相关联的记录
左外连接(left outer join):除了匹配2张表中相关联的记录外,还会匹配左表中剩余的记录,右表中匹配到的字段用null表示
右外连接(right outher join ):除了匹配2张表中相关联的记录外,还会匹配右表中剩余的记录,左表中未匹配到的字段用null表示。在判定左表和右表时,要根据表名出现在outher join的左右位置关系
在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务(多个用户对同一数据进行操作)。并发虽然是必须的,但可能会导致以下的问题
脏读(dirty read):当一个事务正在访问数据并且对数据进行修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的
丢失修改(lost to modify):指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修。列如:事务1读取某表中的数据A=20,事务2也读取A20。事务1修改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失
不可重复读(unrepeatableread):指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的俩次读数据之间,由于第二个事务的修改导致第一个事务俩次读取的数据不一样。这就发生了在一个事务内俩次读到的数据不一样的情况,因此称为不可重复读
幻读(phantom read):幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生幻觉一样,所以称为幻读
不可重复读和幻读区别:
不可重复读的重点是修改比如多次读取一条记录发现其中某些列的值被修改,幻读的重点在于新增或者删除比如多次读取一条记录发现记录增多或者减少
SQL标准定义了四个隔离级别:
read-uncommitted(读取未提交):最低的隔离级别,允许读取尚未提交的数据变更,可能导致脏读、幻读和不可重复读
read-committed(读取已提交):允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
repeatable-read(可重复读):对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己修改,可以阻止脏读和不可重复读,但幻读仍有可能发生
serializable(可串行化):最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读
Mysql innodb存储引擎默认支持的隔离级别是repeatable-read(可重读)
但mysql单表记录数过大时,数据库的crud性能会明显下降,常见优化措施如下:
限定数据的范围
务必禁止不带任务限制数据范围条件的查询语句。比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内;
读/写分离
数据库拆分方案,主库负责写,从库负责读;
垂直分区
根据数据库里面数据表的相关性进行拆分
垂直拆分的优点:
可以使得列数据变小,在查询时减少读取的Block数,减少I/O次数。此外,垂直分区可以简化表的结构,易于维护。
垂直拆分的缺点:
主键会出现冗余,需要管理冗余列,并会引起Join操作,可以通过在应用层进行Join来解决。此外,垂直分区会让事务变得更加复杂;
保持数据表结构不变,通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中,达到了分布式的目的。 水平拆分可以支撑非常大的数据量。
水平拆分是指数据表行的拆分,表的行数超过200万行时,就会变慢,这时可以把一张的表的数据拆成多张表来存放。举个例子:我们可以将用户信息表拆分成多个用户信息表,这样就可以避免单一表数据量过大对性能造成影响。
水平拆分可以支持非常大的数据量。需要注意的一点是:分表仅仅是解决了单一表数据过大的问题,但由于表的数据还是在同一台机器上,其实对于提升MySQL并发能力没有什么意义,所以 水平拆分最好分库 。
因为要是分成多个表之后,每个表都是从 1 开始累加,这样是不对的,我们需要一个全局唯一的 id 来支持。
生成全局 id 有下面这几种方式:
UUID:不适合作为主键,因为太长了,并且无序不可读,查询效率低。比较适合用于生成唯一的名字的标示比如文件的名字。
数据库自增 id : 两台数据库分别设置不同步长,生成不重复ID的策略来实现高可用。这种方式生成的 id 有序,但是需要独立部署数据库实例,成本高,还会有性能瓶颈。
利用 redis 生成 id : 性能比较好,灵活方便,不依赖于数据库。但是,引入了新的组件造成系统更加复杂,可用性降低,编码更加复杂,增加了系统成本
一组为了完成特定功能的SQL语句集,存储在书籍库中,经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象
1.尽量利用一些SQL语句来替代一些小循环,例如聚合函数,求平均函数等
2.中间结果存放于临时表,加索引
3.少使用游标。SQL是个集合语言,对于集合运算具有较高性能。而cursors是过程运算。比如对一个100万行的数据进行查询。游标需要读表100万次,而不使用游标则只需要少量几次读取
4.事务越短越好。SQLserver支持并发操作。如果事务过多过长,或者隔离级别过高,都会造成并发操作的阻塞,死锁。导致查询极慢。CPU占用率极高
5.使用try-catch处理错误异常
6.查找语句尽量不要放在循环内
触发器是一段能自动执行的程序,是一种特殊的储存过程,触发器和普通的存储过程的区别:触发器是当对某一个表进行行操作时触发。如:update,insert,delete这些操作的时候,系统会自动调用执行该表上对应的触发器。SQLserver2005中触发器可以分为俩类:DML触发器和DDL触发器,其中DDL触发器它们会影响多种数据定义语言语句而激发,这些语句有create,alter,drop语句
并发控制一般采用三种方法,分表乐观锁和悲观锁以及时间戳
1.表级锁:开销小,加锁快;不会出现死锁;锁定力度大,发送锁冲突的概率最高,并发读最低
2.行级锁:开销大,加锁慢;会出现死锁;锁定力度最小,发送锁冲突的概率最低,并发度也最高
3.页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定力度界于表锁和行锁之间,并发度一般
1.mylsam(my i 谁暗门)
2.heap
3.merge(门儿知)
4.innodb
5.isam(i 谁暗门)
1.read UNcommited:读到未提交数据
2.read committed :脏读,不可重复读
3.repeatable read:可重读
4.serializable:串行事务
1.char和varchar类型在存储和检索方面有所不同
2.char列长度固定为创建表时声明的长度,长度值范围1-255当char值被存储时,他们被用空格填充到待定长度,检索char值时需删除尾随空格
表格的每一行都由主键唯一标识,一个表只有一个主键。
主键也是候选键。按照管理,候选键可以被指定为主键,并且可以用于任何外键引用
他用来压缩myisam表,这减少了磁盘或内存使用
在myisam static 上的所欲字段有固定宽度。动态myisam表将具有像text,blob等字段,以适应不同长度的数据类型。
myisam static在受损情况下更容易恢复
每当行被更改时,时间戳字段将获取当前时间戳
列设置为auto increment(in库门特) 时,如果在表中达到最大值,会发生什么情况?
他会停止递增,任何进一步的插入都将产生错误,因为秘钥已被使用
怎么才能找出最后一次插入时分配了哪个自动增量?
last_insert_id将返回由auto_increment分配的最后一个值,并且不需要指定表名称
索引通过以下方式为表格定义的
show index from;
%对应于0个或更多字符,_只是like语句中的一个字符
如何在Unix和mysql时间戳之间进行转换?
Unix_timestamp是从mysql时间戳转换为unix时间戳的命令
from_Unixtime是从Unix时间戳转换为mysql时间戳的命令
在 SELECT 语句的列比较中使用=,<>,<=,<,> =,>,<<,>>,<=>,AND,OR 或 LIKE 运算符。
blob(不浪不)是一个二进制对象,可以容纳可变数量的数据,text是一个不区分大小写的blob
blob和text类型之间的唯一区别在于对Blob值进行排序和比较时区分大小写,对text值不区分大小写
mysql_fetch_array 将结果行作为关联数组或来自数据库的常规数组返回
mysql_fetch_object 从数据库返回结果行作为对象
每个myisam表格以三种格式存储在磁盘上
“.frm”文件存储表定义
数据文件具有“.MYD”(Mydata)扩展名
索引文件具有".MYI"(Myindex)扩展名
distinct在所有列上转换为group by ,并与order by 字句结合使用
select distinct ti.a from t1,t2 where t1.a=t2.a
select * from limit 0,50;
任何标准最多可以创建16个索引列
now()命令用于显示当前年份,月份,日期,小时,分钟和秒
current_date()仅显示当前年份,月份和日期
1.tinytext(提米text)
2.text
3.mediumtext(慢定text)
4.longtext
1.concat(A,B)连接俩个字符串值以创建单个字符串输出。通常用于将俩个或多个字段合并为一个字段
2、FORMAT(X, D)- 格式化数字 X 到 D 有效数字。
3、CURRDATE(), CURRTIME()- 返回当前日期或时间。
4、NOW() – 将当前日期和时间作为一个值返回。
5、MONTH(),DAY(),YEAR(),WEEK(),WEEKDAY() – 从日期值中提取给定数据。
6、HOUR(),MINUTE(),SECOND() – 从时间值中提取给定数据。
7、DATEDIFF(A,B) – 确定两个日期之间的差异,通常用于计算年龄
8、SUBTIMES(A,B) – 确定两次之间的差异。
9、FROMDAYS(INT) – 将整数天数转换为日期值
在缺省模式下,mysql是autocommit模式的,所有的数据库更新操作都会即时提交,所有在缺省情况下,mysql是不支持事务的。但是如果你的mysql表类型是使用innodb tables 或bdb tables 的话,你的mysql就可以使用事务处理,使用set autocommit=0就可以使用mysql允许在非autocommit模式,在非autocommit模式下,你必须使用commit来提交你的更改,或者用rollback来回滚你的更改
MySQL 服务器通过权限表来控制用户对数据库的访问,权限表存放在 MySQL 数据库里,由 MySQL_install_db 脚本初始化。这些权限表分别 user,db,table_priv(不润四),columns(可老迷死)_priv和host
字符串类型是:
1、SET
2、BLOB
3、enum(按呐门)
4、CHAR
5、TEXT
1.设计良好的数据库结构,允许部分数据冗余,尽量避免join查询,提高效率
2.mysql库主从读写分离
3.选择合适的表字段数据类型和存储引擎,适当的添加索引
4.找规律分表,减少单表中的数据量提高查询速度
5.添加缓存机制,比如memcached,apc等
6.不经常改动的页面,生成静态页面
7.写高效率的SQL
1.读写分离
2.分段加锁
3.减少锁持有时间
4.多个线程尽量以相同的顺序去获取资源不能将锁的粒度过于细化,不然可能会出现线程的加锁和释放次数过多,反而效率不如一次加一把大锁
B+数,经过优化B+树
主要是在所有的叶子结点中增加了指向下一个叶子节点的指针,因此innodb建议为大部分表使用默认自增的主键作为主索引
1.以%开头的like语句,模糊匹配
2.or语句前后没有同时使用索引
3.数据类型出现隐式转化(如varchar不加单引号的话可能会自动转换为int类型)
1.SQL语句及索引的优化
2.数据库表结构的优化
3.系统配置的优化
4.硬件的优化
1.使用连接join来代替子查询
2.使用union来代替手动创建的临时表
3.事务处理
4.锁定标,优化事务处理
5.使用外键,优化锁定表
6.建立索引
07.优化查询语句
索引是一种特殊的文件(InnoDB 数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。
普通索引(由关键字 KEY 或 INDEX 定义的索引)的唯一任务是加快对数据的访问速度。
普通索引允许被索引的数据列包含重复的值。如果能确定某个数据列将只包含彼此各不相同的值,在为这个数据列创建索引的时候就应该用关键字 UNIQUE 把它定义为一个唯一索引。也就是说,唯一索引可以保证数据记录的唯一性。
主键,是一种特殊的唯一索引,在一张表中只能定义一个主键索引,主键用于唯一标识一条记录,使用关键字 PRIMARY KEY 来创建。
索引可以覆盖多个数据列,如像 INDEX(columnA, columnB)索引,这就是联合索引。
索引可以极大的提高数据的查询速度,但是会降低插入、删除、更新表的速度,因为在执行这些操作时,还要操作索引文件
SQL注入产生的原因:程序开发过程中不注意规范书写SQL语句和对特殊字符进行过滤,导致客户端可以通过全局变量post和get提交,一些SQL语句正常执行
防止SQL注入的方式:
开启配置文件中的magic_quotes_gpc和magic_quotes_runtime设置执行SQL语句时使用addslashes进行SQL语句转换
SQL语句书写尽量不要省略双引号和单引号
过滤掉SQL语句中的一些关键词:update,insert,delete,select,*
提高数据库表和字段的命名技巧,对一些重要的字段根据程序的特点命名,取不易被猜到的
字段类型优先级:整形>data,time>enum,char>varchar>blob,text优先考虑数字类型,其次是日期或者二进制类型,最后是字符串类型,同级别的数据类型,应该优先选择占用空间小的数据类型
Datatime:以YYYY-MM-DD HH:MM:SS格式存储日期时间,精确到秒,占用8个字节得存储空间,datatime类型与时区无关
Timestamp:以时间戳格式存储,占用4个字节,范围小1970-1-1到2013-1-19,显示依赖于所指定得时区,默认在第一列行的数据修改时可以自动得修改
timestamp列得值
Date:(生日)占用字节数比使用字符串.datatime.int存储要少,使用date只需要3个字节,存储日期月份,还可以利用日期时间函数进行日期间的计算
Time:存储时间部分得数据
注意:不要使用字符串类型来存储日期时间数据(通常比字符串占用得存储空间小,在进行查找过滤可以利用日期得函数)
使用int存储日期时间不如使用timestamp类型
1.索引的目的是什么?
快速访问数据表中的特定信息,提高检索速度
创建唯一索引,保证数据库表中每一行数据的唯一性
加速表和表之间的连接
使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间
2.索引对数据库系统的负面影响是什么?
创建索引和维护索引需要耗费时间,这个时间随着数据量的增加而增加;
索引需要占用物理空间,不光是表需要占用数据空间,每个索引也需要占用物理空间;
当对表进行增,删,改的时候索引也要动态维护,这样就降低了数据的维护速度。
3.为数据表建立索引的原则有哪些?
在最频繁使用的、用以缩小查询范围的字段上建立索引
在频繁使用的,需要排序的字段上建立索引
4.什么情况下不易建立索引
对于查询中很少涉及的列或者重复值比较多的列,不宜建立索引
对于一些特殊的数据类型,不宜建立索引,比如文本字段(text)等
先说什么是交叉连接:交叉连接又叫笛卡尔积,他是指不使用任何条件,直接将一个表的所有记录和另一个表中的所有记录一一匹配。
内连接则是只有条件的交叉连接,根据某个条件筛选出符合条件的记录,不符合条件的记录不会出现在结果集中,即内连接只连接匹配的行
外连接 其结果集中不仅包含符合连接条件的行,而且还会包括左表,右表或俩个表中的所有数据行,这三种情况依次称之为左外连接,右外连接,和全外连接
左外连接,也称为左连接,,左表为主表,左表中的所有记录都会出现在结果集中,对于那些在右表中并没有匹配的记录,仍然要显示,右边对应的那些字段值以NULL 来填充。右外连接,也称右连接,右表为主表,右表中的所有记录都会出现在结果集中。左连接和右连接可以互换,MySQL 目前还不支持全外连接
事务是用户定义的一个数据库操作序列,这些操作要么全做要么全不做,是一个不可分割的工作单位,事务回滚是指将该事务已经完成的对数据库的更新操作撤销
要同时修改数据库中俩个不同表时,如果他们不是一个事务的话,当第一个表修改完,可能第二个表修改过程中出现了异常而没能修改,此时就只有第二个表依旧是未修改之前的状态,而第一个表已经被修改完毕。而当你把他们设定为一个事务的时候,当第一个表修改完,第二表修改出现异常而没能修改,第一个表和第二个表都要回到未修改的状态,这就是所谓的事务回滚
SQL语句包括数据定义(DDL)数据操作(DML)数据控制(DCL)数据查询(DQL)四个部分
数据定义:create table ,alter table,drop table,craete/drop index等
数据操纵:select ,insert,update,delete
数据控制:grant,revoke
数据查询:select
数据完整性(Data integrity)是指数据的精通(accuracy)和可靠性(reliability)
分为以下四类:
1.实体完整性:规定表的每一行在表中是惟一的实体
2.域完整性:是指表中的列必须满足某种特定的数据类型约束,其中约束又包括取值范围,精度等规定
3.参照完整性:是指俩个表的主关键字和外关键字的数据应一致,保证了表之间的数据的一致性,防止了数据丢失或无意义的数据在数据库中扩散
4.、用户定义的完整性:不同的关系数据库系统根据其应用环境的不同,往往还需要一些特殊的约束条件。用户定义的完整性即是针对某个特定关系数据库的约束条件,它反映某一具体应用必须满足的语义要求。与表有关的约束:包括列约束(NOT NULL(非空约束))和表约束(PRIMARY KEY、foreign key、check、UNIQUE) 。
数据库是一个多用户使用的共享资源。当多个用户并发的存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性
加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发送请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放之前,其他的事务不能对此数据对象进行更新操作。
基本锁类型:锁包括行级锁和表级锁
视图是一种虚拟的表,具有和物理表相同的功能。可以对视图进行增,改,查,操作,视图通常是有一个表或者多个表的行或列的子集。对视图的修改不影响基本表。它使得我们获取数据更容易,相比多表查询
游标:是对查询出来的结果集作为一个单元来有效的处理。游标可以定在该单元中的特定行,从结果集的当前行检索一行或多行。可以对结果集当前行做修改。一般不使用游标,但是需要逐条处理数据的时候,游标显得十分重要
存储过程是一个预编译的SQL语句,优点是允许模块化的设计,就是说只需要创建一次,以后在该程序中就可以调用多次。如果某次操作需要执行多次SQL,使用存储过程比单纯SQL语句执行要快。可以用一个命令对象来调用存储过程
第一范式:1NF是对属性的原子性约束,要求属性具有原子性,不可再分解;
第二范式:2NF是对记录的唯一性约束,要求记录有唯一标识,即实体的唯一性;
第三范式:3NF是对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余。
范式化设计优缺点:
优点:
可以尽量的减少数据冗余,使得更新快,体积小
缺点:
对于查询需要多个表进行关联,减少写的效率增加读的效率,更难进行索引
优化:
反范式化:
优点:可以减少表的关联,可以更好的进行索引优化
缺点:数据冗余以及数据异常,数据得修改需要更多的成本
基本表是本身独立存在的表,在SQL中一个关系就对应一个表。视图是从一个或几个基本表导出的表。视图本身不独立存储在数据库中,是一个虚表
1.视图能够简化用户的操作
2.视图使用户能以多种角度看待同一数据
3.视图为数据库提供了一定程度的逻辑独立性
4.视图能够对机密数据提供安全保护
null这个值表示未知,他不表示空字符串。使用 is null 进行null判断
主键,外键和索引的区别
定义:
主键 唯一标识一条记录,不能有重复的,不允许为空
外键 表的外键是另一表的主键,外键可以有重复的,可以是空值
索引 该字段没有重复值,但可以有一个空值
作用:
主键 用来保证数据完整性
外键 用来和其他表建立联系的
索引 提高查询排序的速度
个数:
主键 主键只能有一个
外键 一个表可以有多个外键
索引 一个表可以有多个唯一索引
check限制,它在数据库表格里被定义,用来限制输入该列的值。触发器也可以被用来限制数据库表格里的字段能够接受的值,但是这种办法要求触发器在表格里被定义,这可能会在某些情况下影响到性能
1.用exists替代in,用not exists替代not in
2.避免在索引列上使用计算
3.避免在索引列上使用 is null和is not null
4.对查询进行优化,应尽量避免全表扫描,首先考虑在where及order by 涉及的列上建立索引
5.避免在where字句中对字段进行null值判断,否则将导致引擎放弃使用索引而进行全表扫描
6.避免在where字句中对字段进行表达式操作,否则将导致引擎放弃使用索引而进行全表扫描
乐观锁认为一个用户读数据的时候,别人不会去写自己所读的数据;悲观锁就刚好相反,觉得自己读数据库的时候,别人可能刚好在写自己刚读的数据,其实就是持一种比较保守的态度;时间戳就是不加锁,通过时间戳来控制并发出现的问题
悲观锁就是在读取数据的时候,为了不让别人修改自己读取的数据,就会先对自己读取的数据加锁,只有自己把数据读完了,才允许别人修改那部分数据,或者反过来说,就是自己修改某条数据的时候,不允许别人读取该数据,只有等自己的整个事务提交了,才释放自己加上的锁,才允许其他用户访问那部分数据
时间戳就是在数据库表中单独加一列时间戳,比如“timestamp”,每次读出来的时候,把该字段也读出来,当写回去的时候,把该字段加1,提交之前,跟数据库的该字段比较一次,如果比数据库值大的话,就允许保存,否则不允许保存,这种处理方法虽然不使用数据库系统提供的锁机制,但是这种方法可以大大提高数据库处理的并发量,以上悲观锁所说的加“锁”,其实分为几种锁,分别是:排它锁(写锁)和共享锁(读锁)
行级锁是一种排他锁,防止其他事务修改此行;在使用以下语句时,oracle会自动应用行级锁:
1.insert,update,delete,select
2.select ... for update 语句允许用户一次锁定多条记录进行更新
3.使用commit或rollback 语句释放锁
表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分mysql引擎支持。最常使用myisam与innodb都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁)
页级锁是mysql中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。bdb支持页级锁