数据库基础知识

Posted by 谢玄xx on April 29, 2022

数据库是必须要学的哇!在这里做一些微记录吧。

写在前面——为什么大家都在学习数据库?

随着“敏捷开发”概念盛行,运维开发正在一体化,这就要求开发人员了解数据库,从而针对项目进行数据库的优化。

数据库本是Oracle的天下,但随着阿里提出去Oracle化,大家越来越倾向使用开源的MySQL库。

数据库概述

SQL(Structured Query Language:结构化查询语言)是用于管理关系数据库管理系统(RDBMS)的一种语言。SQL的范围包括数据插入、查询、更新和删除,数据库模式创建和修改,以及数据访问控制。

数据库基本语法——SQL语句

SQL语句对程序的大小写不敏感。大写和小写是一样的。

一些最重要的 SQL 命令:
SELECT - 从数据库中提取数据
UPDATE - 更新数据库中的数据
DELETE - 从数据库中删除数据
INSERT INTO - 向数据库中插入新数据
CREATE DATABASE - 创建新数据库
ALTER DATABASE - 修改数据库
CREATE TABLE - 创建新表
ALTER TABLE - 变更(改变)数据库表
DROP TABLE - 删除表
CREATE INDEX - 创建索引(搜索键)
DROP INDEX - 删除索引

SELECT

在MySQL中,SELECT语句默认返回所有匹配的行。它们可能是指定表中的每个行。

  • select语句的基本格式为:
    SELECT 要查询的列名 FROM 表名字 WHERE 限制条件;
    
  • 如果要查询表的所有内容,则把 要查询的列名 用一个星号 * 号表示,代表要查询表中所有的列。 而大多数情况,我们只需要查看某个表的指定的列,比如要查看employee 表的 name 和 age:
    SELECT name,age FROM employee;
    
  • SELECT 语句常常会有 WHERE 限制条件,用于达到更加精确的查询。WHERE限制条件可以有数学符号 (=,<,>,>=,<=) ,刚才我们查询了 name 和 age,现在稍作修改:
    SELECT name,age FROM employee WHERE age>25;
    
  • 或者查找一个名字为 Billy 的员工:
    SELECT name,age,phone FROM employee WHERE name='Billy';
    
  • 为了使查询结果看起来更顺眼,我们可能需要对结果按某一列来排序,这就要用到 ORDER BY 排序关键词。默认情况下,ORDER BY的结果是升序排列,而使用关键词ASC和DESC可指定升序或降序排序:
SELECT name,age,salary,phone FROM employee ORDER BY salary DESC;

一些特殊的比较逻辑

<>:不等符号
=:相等符号 在 AND 和OR都存在的情况下,AND的优先级更高。

常见问题

MySQL有哪几种数据存储引擎?有什么区别?

通过在MySQL中输入show ENGINES就可以看到数据库支持的各引擎名称。最常用的是InnoDB和MyISAM。

MyISAM & InnoDB的区别:

  1. 存储文件方式不同。MyISAM每个表有两个文件——MYD(数据文件)和MYISAM(索引文件),而InnoDB每个表只有一个文件,也即.IBD文件。
  2. InnoDB支持事务(transactions),XA事务,savepoints(及时存档,部分回滚),支持行级锁(row-level locking),支持外键(foreign keys)。

什么是脏读、幻读、不可重复读?要怎么处理?

  • 脏读就是指当一个事务A正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务B也访问这个数据,然后使用了这个数据。脏读也俗称“读未提交”,顾名思义,就是某一事务B读取到了事务A未提交的数据。
  • 幻读是指当事务”不是独立执行时”发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。例如,一个编辑人员更改作者提交的文档,但当生产部门将其更改内容合并到该文档的主复本时,发现作者已将未编辑的新材料添加到该文档中。如果在编辑人员和生产部门完成对原始文档的处理之前,任何人都不能将新材料添加到文档中,则可以避免该问题。
  • 不可重复读是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不 可重复读。例如,一个编辑人员两次读取同一文档,但在两次读取之间,作者重写了该文档。当编辑人员第二次读取文档时,文档已更改。原始读取不可重复。如果只有在作者全部完成编写后编辑人员才可以读取文档,则可以避免该问题。

  • 一言蔽之,不可重复读的重点是修改——同一事务,两次读取到的数据不一样;幻读的重点在于新增或者删除——同样的条件 , 第1次和第2次读出来的记录数不一样;脏读——强调的是第二个事务读到的不够新。

事务的基本特性和隔离级别有哪些?

事务的基本特性(ACID)共4大性质:

  1. 原子性(Atomicity):化学中的原子指不可再分的基本微粒,数据库中原子性强调事务是一个不可分割的整体,事务开始后所有操作要么全部成功,要么全部失败,不可能停滞在中间某个环节。如果事务执行过程中出错就会回滚到事务开始前的状态,所有的操作就像没有发生一样不会对数据库有任何影响。
  2. 一致性(Consistency):事务必须使数据库从一个一致性状态变换到另一个一致性状态,即一个事务执行之前和执行之后都必须处于一致性状态。拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还是5000,这就是事务的一致性。
  3. 隔离性(Isolation):当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰。多个并发事务之间要相互隔离,比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转入钱。
  4. 持久性(Durability):一个事务一旦被提交,则对数据库的所有更新将被保存到数据库中,不能回滚。

数据库的事务隔离级别分为四种(级别递减):

  1. Serializable (串行化):最严格的级别,事务串行执行,资源消耗最大;
  2. REPEATABLE READ (重复读) :保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,但不能避免“幻读”,但是带来了更多的性能损失。
  3. READ COMMITTED (提交读):大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”,但不能避免“幻读”和“不可重复读取”。该级别适用于大多数系统。
  4. Read Uncommitted (未提交读) :事务中的修改,即使没有提交,其他事务也可以看得到,会导致“脏读”、“幻读”和“不可重复读取”。

MySQL的锁有哪些?

从锁的粒度来区分,分为行锁,表锁和全局锁。

  • 行锁

行锁的优点是加锁粒度小,但缺点是加锁资源开销比较大。innoDB支持行锁。行锁又分为共享锁,排他锁和自增锁三种。

  1. 共享锁——读锁。多个事务可以对同一个数据共享一把锁。持有锁的事务都可以访问数据,但只能读不能修改。使用方法为:select xxx lock in share mode
  2. 排他锁——写锁。只有一个事务可以获得排他锁,其他事务都不能获取该行的锁。innoDB会对update/delete/insert语句自动添加排他锁,如:select xxx for update
  3. 自增锁——通常针对MySQL当中的自增字段。如果出现“事务回滚”的情况,数据会回滚,但自增序列不会回滚,相当于“锁住了”。
  • 表锁

表锁的优点是加锁资源开销比较小,对应的缺点就是加锁粒度比较大啦。目前innoDB和MYISAM都支持表锁。同样地,表锁也分为共享读锁和排他写锁。此外还有一种意向锁。

  1. 共享锁——读锁
  2. 排他锁——写锁
  3. 意向锁——也是由innoDB自动添加。
  • 全局锁

Flush tables with read lock. 加了全局锁后,整个数据库实例都处于只读状态。所有的数据变更操作都会被挂起,一般会在全库数据备份的时候用。

什么是间隙锁?

间隙锁是常用锁算法中的一种,还有记录锁和Next-Key锁

  • 间隙锁——在RR隔离级别下才会产生间隙锁。其目的是锁住一个区间,防止幻读。如user : userid(1, 4, 9)之后,update user set xxx where userid = 5; REPEATABLE READ 就会使间隙锁锁住(5,9)区间。 请注意,间隙锁一定是锁一个范围,而不锁一个具体的记录。(-xx, 1)(1,4)(4,9)(9,xx)
  • 记录锁——锁一个具体的记录。
  • Next-Key锁——间隙锁 + 右记录锁,即左开右闭。如(-xx, 1](1,4](4,9](9,xx)