Mysql是关系型数据库,是开源的,常用的数据库引擎是InnoDB(支持事务)、MyISAM(不支持事务)
使用Mysql时,不同的表还可以使用不同的数据库引擎,很常用的是InnoDB
数据库表每一行都是一个记录
,每一列称为一个字段
,每个字段都要定义数据类型
数据库表要建立”一对多“,”多对多“或”一对一“的关系
在关系数据库中,关系是通过主键和外键来进行维护的
主键确定一条唯一的记录,一张数据库表中不能存在两条主键一样的数据
选取主键的一个基本原则是:不适用任何业务相关的字段作为主键
常见的可作为主键字段的类型有:
BIGINT
自增整数类型:数据库会自动为每一条记录分配一个自增整数
BIGINT NOT NULL AUTO_INCREMENT
全局唯一GUID类型:使用一种全局唯一的字符串作为主键。GUID
算法通过网卡MAC地址、时间戳和随机数保证任意计算机在任意时间生成的字符串都是不同的。大部分编程语言都内置了GUID算法,可以自己预算出主键
关系数据库实际上还允许通过多个字段唯一标识记录,即两个或以上的字段都可以设置为主键,这种主键被称为联合主键
对于联合主键,允许一列是重复的,只要不是所有的主键都重复就可以
不过联合主键用的很少,毕竟会使得关系表更复杂
a表的外键是b表的主键,通过外键把a、b表关联起来
通过定义外键约束,数据库可以保证不会插入无效的数据
通过外键可以实现关系数据库一对一、一对多、多对一的关系
索引是关系数据库中对某一列或多列的值进行预排序的数据结构。通过使用索引,可以让数据库不再全表扫描,而是直接定位到符合条件的数据,能大大加快查询速度
如果要经常根据score
列进行查询,就可以对score
列建立索引:
ALTER TABLE students
ADD INDEX idx_score(score);
索引名称是任意的,如果索引有多列,用,
进行隔开:
ALTER TABLE students
ADD INDEX idx_score_name(score,name)
一张数据库表可以创建多个索引
索引的效率取决于索引列的值是否散列,即该列的值如果越互不相同,那么索引的效率越高。反过来,如果记录的列存在大量相同的值,为该列创建索引就没有多大意义
对于主键,关系型数据库会自动为其创建主键索引。使用主键索引的效率是最高的,因为主键会保证绝对唯一
优点
提高查询效率
缺点
在插入、更新、删除记录时,要同时修改索引,因为索引越多,插入、更新、删除数据的速度就越慢
有些列看上去数据会是唯一的,比如像身份证号、手机号等,这些虽然跟业务紧密相关不能作为主键,但是可以为它们设置唯一索引(既创建了索引,又建立了字段唯一的性质,即这个字段值是唯一的,不能有相同的两个记录)
例如:
ALTER TABLE students
ADD UNIQUE INDEX uni_idCard(idCard);
也可以只对某一列添加唯一约束
,而是唯一索引
:
ALTER TABLE students
ADD CONSTRAINT uni_name UNIQUE(name);
这种唯一约束虽然没有创建索引,但是保证了该列的值是唯一的,不能出现相同的两条记录。
LIMIT 3 OFFSET 0
:指从第0条数据开始,取3条数据展示,与LIMIT 3
是相同的效果
LIMIT 15 OFFSET 30
可以简写成LIMIT 30,15
,意思是从第30条数据开始取15条数据展示
使用LIMIT m OFFSET n
可以对结果集进行分页,每次查询只返回结果集的一部分
查询某张表一共有多少条记录,可以使用内置函数count()
select count(*) from students;
虽然查询结果是一个数字,但是查询结果其实还是一个二维表,只不过只有一行一列,并且列名是count(*)
可以设置别名为num
:
select count(*) num from students;
sum():计算某一列的合计值,该列的数据类型必须为数值型
avg():计算某一列的平均值,该列的数据类型必须为数值型
max():计算某一列的最大值
min():计算某一列的最小值
ps: max()和min()并不限制是数值类型,如果是字符类型的话,分别会返回排序最后和排序最前的字符
ps:如果聚合查询的where条件没有匹配到任何行,那么count()
会返回0,而sum()
、max()
、min()
、avg()
会返回NULL
inner join
内连接,只返回两张表同时存在的数据
left outer join
左外连接,返回左表都存在的数据,右表不存在的数据显示为NULL
right outer join
右外连接,返回右表都存在的数据,左表不存在的数据显示为NULL
full outer join
全连接,把两张表的记录都显示,不存在的数据显示为NULL
Atomicity(原子性):一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要不全部提交成功,要不全部回滚。对于一个事务来说,不可能只执行其中的一部分操作
Consistency(一致性):数据库总是从一个一致性状态转换到另一个一致性状态
Isolation(隔离性):通常来说,一个事务所做的修改在最终提交之前,对其他事务是不可见的
Durability(持久性):一旦事务提交,其所做的修改就会永久保存到数据库中。此时即使系统崩溃,修改的数据也不会丢失。
更新丢失(lost update):当多个事务(A、B、C)同时对某一列进行更新数据的操作 ,由于每个事务都不知道其他事务所做的更新操作,就会发生更新丢失的问题,最后操作更新的事务会覆盖掉之前事务所做的更新。----如果有事务在进行更新并还没提交事务之前,另一个事务无法访问这个文件,则可以避免这类情况
脏读(dirty reads):事务A正在对某一列进行数据修改,在这个事务还没提交之前,事务B来读取这条记录,读取到的是修改后的数据,但事务A进行了回滚,事务B再进行读取数据的话,此时事务B读取到的是修改前的数据。即事务B读取到了“脏数据”
不可重复读(non-repeatable reads):事务A在读取某些数据后的某个时间,再次读取以前读过的数据,可能会发现其读出的数据发生了变化。这种现象叫”不可重复读“。
即在一个事务内,多次重复读取该数据,但是因为有其他事务修改了该数据,导致多次读取出来的数据不一致。
幻读(phantom reads):一个事务按相同的查询条件重新读取以前的数据,可能会发现其他事务插入了满足其查询条件的新数据,这称为“幻读”。
即在一个事务内,多次重复读取该数据,但是因为有其他事务对数据进行了插入或删除,导致动次读取出来的数据不一致
ps:不可重复读和幻读的区别:
不可重复读的重点在于修改,同一事务,同样的条件,第一次读出的数据和第二次读出的数据不一致(因为有其他事务提交了修改)
幻读的重点在于新增或删除,同一事务,同样的条件,第一次读出的数据和第二次读出的数据不一致(因为有其他事务提交了插入或删除)
sql标准定义了4种事务隔离级别,每一种级别都规定了一个事务中所做的修改,哪些在事务内或事务间是可见的,哪些是不可见的。低级别的隔离级别一般支持更高的并发处理,并且拥有更低的系统开销
以下列出的事务隔离级别,从低到高列举:
Read Uncommitted(读取未提交的内容)
读未提交。所有的事务都可以看见其他未提交事务的结果,这种隔离级别会引发“脏读”。
但是这种隔离级别很少应用在实际应用中,因为性能相比其他隔离级别来说也不是好很多
Read Committed(读取已提交的内容)
读已提交。这是大多数数据库系统的默认隔离级别(但不是mysql默认的隔离级别)
一个事务只能看见已经提交的事务所做的改变,未修改的无法看见,所以不会产生“脏读”。
但是这种会产生“不可重复读”
Repeatable Read(可重复读)
这是mysql的默认事务隔离级别。
确保同一个事务的多个实例在并发读取数据的时候,读取到的是同一个数据
可能会导致"幻读",InnoDB和FAlcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决幻读问题;InnoDB还通过间隙锁解决幻读问题
Serializable(可串行化)
是最严格的隔离级别。在Serializable隔离级别下,所有事务按照次序依次执行,因此脏读、不可重复读、幻读的情况是不会出现的
但是虽然隔离级别最高,但是由于事务是串行执行,效率会大大降低,性能也会急剧降低。如果没有特别的需求的话,这个隔离级别一般不会应用