概念:事务(txn)是一系列在共享数据库上执行的行为,以达到更高层次更复杂逻辑的功能。事务是 DBMS 中最基础的单位,事务不可分割。
特性:ACID,是指在可靠数据库管理系统(DBMS)中,事务(transaction)所应该具有的四个特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
(1)原子性:是指事务是一个不可再分割的工作单位,事务中的操作要么都发生,要么都不发生。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
(2)一致性:是指事务使得系统从一个一致的状态转换到另一个一致状态。这是说数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。
(3)隔离性:多个事务并发访问时,事务之间是隔离的,一个事务不应该影响其它事务运行效果。这指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。
(4)持久性:意味着在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。即使出现了任何事故比如断电等,事务一旦提交,则持久化保存在数据库中。
本地事务数据库断电的这种情况,它是怎么保证数据一致性的呢?
我们使用 SQL Server来举例,我们知道我们在使用 SQL Server 数据库是由两个文件组成的,一个数据库文件和一个日志文件。通常情况下,日志文件都要比数据库文件大很多。数据库进行任何写入操作的时候都是要先写日志的,同样的道理,我们在执行事务的时候数据库首先会记录下这个事务的 redo 操作日志,然后才开始真正操作数据库,在操作之前首先会把日志文件写入磁盘,那么当突然断电的时候,即使操作没有完成,在重新启动数据库时候,数据库会根据当前数据的情况进行 undo 回滚或者是 redo 前滚,这样就保证了数据的强一致性。
1) 第一范式:
数据库表中的字段都是单一属性的,不可再分;每一个属性都是原子项,不可分割;如果实体中的某个属性有多个值时,必须拆分为不同的属性。通俗解释,1NF是关系模式应具备的最起码的条件,如果数据库设计不能满足第一范式,就不称为关系型数据库。也就是说,只要是关系型数据库,就一定满足第一范式。
2) 第二范式:
数据库表中不存在非关键字段对任一候选关键字段的部分函数依赖,即符合第二范式;如果一个表中某一个字段 A 的值是由另外一个字段或一组字段 B 的值来确定的,就称为 A 函数依赖于 B;当某张表中的非主键信息不是由整个主键函数来决定时,即存在依赖于该表中不是主键的部分或者依赖于主键一部分的部分时,通常会违反 2NF。
3) 第三范式:
在第二范式的基础上,数据表中如果不存在非关键字段对任一候选关键字段的传递函数依赖则符合 3NF;第三范式规则查找以消除没有直接依赖于第一范式和第二范式形成的表的主键的属性。我们为没有与表的主键关联的所有信息建立了一张新表。每张新表保存了来自源表的信息和它们所依赖的主键;如果某一属性依赖于其他非主键属性,而其他非主键属性又依赖于主键,那么这个属性就是间接依赖于主键,这被称作传递依赖于主属性。 通俗理解:一张表最多只存 2 层同类型信息 。
概念:数据库索引好比是一本书前面的目录,能加快数据库的查询速度。索引是对数据库表中一个或多个列(例如,employee 表的姓氏 (lname) 列)的值进行排序的结构。如果想按特定职员的姓来查找他或她,则与在表中搜索所有的行相比,索引有助于更快地获取信息。
1) 优点:
大大加快数据的检索速度; 创建唯一性索引,保证数据库表中每一行数据的唯一性;加速表和表之间的连接; 在使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间。
2) 缺点:
索引需要占用数据表以外的物理存储空间;创建索引和维护索引要花费一定的时间;当对表进行更新操作时,索引需要被重建,这样降低了数据的维护速度。
类型
唯一索引——UNIQUE
例如:create unique index stusno on student(sno);
表明此索引的每一个索引值只对应唯一的数据记录,对于单列惟一性索引,这保证单列不包含重复的值。对于多列惟一性索引,保证多个值的组合不重复。
主键索引——primary key
数据库表经常有一列或列组合,其值唯一标识表中的每一行。该列称为表的主键。 在数据库关系图中为表定义主键将自动创建主键索引,主键索引是唯一索引的特定类型。该索引要求主键中的每个值都唯一。当在查询中使用主键索引时,它还允许对数据的快速访问。
聚集索引(也叫聚簇索引)——cluster
在聚集索引中,表中行的物理顺序与键值的逻辑(索引)顺序相同。一个表只能包含一个聚集索引,如果某索引不是聚集索引,则表中行的物理顺序与键值的逻辑顺序不匹配。与非聚集索引相比,聚集索引通常提供更快的数据访问速度。
实现方式
B+树、散列索引、位图索引
1) 聚集索引表示表中存储的数据按照索引的顺序存储,检索效率比非聚集索引高,但对数据更新影响较大。非聚集索引表示数据存储在一个地方,索引存储在另一个地方,索引带有指针指向数据的存储位置,非聚集索引检索效率比聚集索引低,但对数据更新影响较小。
2) 聚集索引一个表只能有一个,而非聚集索引一个表可以存在多个。聚集索引存储记录是物理上连续存在,而非聚集索引是逻辑上的连续,物理存储并不连续。
Innodb 引擎:提供了对数据库 ACID 事务的支持,并且实现了 SQL 标准的四种隔离级别,关于数据库事务与其隔离级别的内容请见数据库事务与其隔离级别这篇文章。该引擎还提供了行级锁和外键约束,它的设计目标是处理大容量数据库系统,它本身其实就是基于 MySQL 后台的完整数据库系统,MySQL 运行时 Innodb 会在内存中建立缓冲池,用于缓冲数据和索引。但是该引擎不支持 FULLTEXT 类型的索引,而且它没有保存表的行数,当 SELECT COUNT(*) FROM TABLE 时需要扫描全表。当需要使用数据库事务时,该引擎当然是首选。由于锁的粒度更小,写操作不会锁定全表,所以在并发较高时,使用 Innodb引擎会提升效率。但是使用行级锁也不是绝对的,如果在执行一个 SQL 语句时 MySQL不能确定要扫描的范围,InnoDB 表同样会锁全表。
MyIASM引擎: 是 MySQL 默认的引擎,但是它没有提供对数据库事务的支持,也不支持行级锁和外键,因此当 INSERT(插入)或 UPDATE(更新)数据时即写操作需要锁定整个表,效率便会低一些。不过和Innodb不同,MyIASM中存储了表的行数,于是SELECT COUNT(*) FROMTABLE 时只需要直接读取已经保存好的值而不需要进行全表扫描。如果表的读操作远远多于写操作且不需要数据库事务的支持,那么 MyIASM 也是很好的选择。
大尺寸的数据集趋向于选择 InnoDB 引擎,因为它支持事务处理和故障恢复。数据库的大小决定了故障恢复的时间长短,InnoDB 可以利用事务日志进行数据恢复,这会比较快。主键查询在 InnoDB 引擎下也会相当快,不过需要注意的是如果主键太长也会导致性能问题,关于这个问题我会在下文中讲到。大批的 INSERT 语句(在每个 INSERT 语句中写入多行,批量插入)在 MyISAM 下会快一些,但是 UPDATE 语句在 InnoDB 下则会更快一些,尤其是在并发量大的时候。
1) 隔离级别高的数据库的可靠性高,但并发量低,而隔离级别低的数据库可靠性低,但并发量高,系统开销小。
2) READ UNCIMMITTED(未提交读),事务中的修改,即使没有提交,其他事务也可以看得到,比如说上面的两步这种现象就叫做脏读,这种隔离级别会引起很多问题,如无必要,不要随便使用;这就是事务还没提交,而别的事务可以看到他其中修改的数据的后果,也就是脏读;
3) READ COMMITTED(提交读),大多数数据库系统的默认隔离级别是 READ COMMITTED,这种隔离级别就是一个事务的开始,只能看到已经完成的事务的结果,正在执行的,是无法被其他事务看到的。这种级别会出现读取旧数据的现象;
4) REPEATABLE READ(可重复读),REPEATABLE READ 解决了脏读的问题,该级别保证了每行的记录的结果是一致的,也就是上面说的读了旧数据的问题,但是却无法解决另一个问题,幻行,顾名思义就是突然蹦出来的行数据。指的就是某个事务在读取某个范围的数据,但是另一个事务又向这个范围的数据去插入数据,导致多次读取的时候,数据的行数不一致。虽然读取同一条数据可以保证一致性,但是却不能保证没有插入新的数据。
5) SERIALIZABLE(可串行化),SERIALIZABLE 是最高的隔离级别,它通过强制事务串行执行(注意是串行),避免了前面的幻读情况,由于他大量加上锁,导致大量的请求超时,因此性能会比较底下,再特别需要数据一致性且并发量不需要那么大的时候才可能考虑这个隔离级别。