谈一下数据库

谈一下数据库

来吧 全梳理一遍

SQL是什么

SQL 的全称是 Structure Query Language ,结构化的查询语言,它是一种针对表关联关系所设计的一门语言,我们常见的MySQL就是其中的一种,今天主要来梳理MySQL,MySQL 是一种关系型数据库,MySQL是我们数据库入门的第一步。

这里默认大家都已经安装好了mysql,不管是win还是linux相信大家都已经掌握,什么版本切换,什么密码,什么权限相信都难不住大家,让我们直接进入MySQL即可。

MySQL的存储引擎

InnoDB

InnoDB是 MySQL (MySQL5.5.5 之后)默认的事务型存储引擎,只有在需要它不支持的特性时,才考虑使用其它存储引擎。

InnoDB 支持外键操作。

InnoDB 默认的锁粒度行级锁,并发性能比较好,会发生死锁的情况。

和 MyISAM 一样的是,InnoDB 存储引擎也有 .frm文件存储表结构 定义,但是不同的是,InnoDB 的表数据与索引数据是存储在一起的,都位于 B+ 数的叶子节点上,而 MyISAM 的表数据和索引数据是分开的。

InnoDB 支持事务操作,具有事务 ACID 隔离特性,默认的隔离级别是可重复读(repetable-read)、通过MVCC(并发版本控制)来实现的。能够解决脏读不可重复读的问题。

InnoDB 有安全的日志文件,这个日志文件用于恢复因数据库崩溃或其他情况导致的数据丢失问题,保证数据的一致性。

InnoDB 和 MyISAM 支持的索引类型相同,但具体实现因为文件结构的不同有很大差异。

增删改查性能方面,如果执行大量的增删改操作,推荐使用 InnoDB 存储引擎,它在删除操作时是对行删除,不会重建表。

MyISAM

设计简单,数据以紧密格式存储。对于只读数据,或者表比较小、可以容忍修复操作,则依然可以使用它。

MyISAM不支持事务操作,ACID 的特性也就不存在了,这一设计是为了性能和效率考虑的。

MyISAM不支持外键操作,如果强行增加外键,MySQL 不会报错,只不过外键不起作用。

MyISAM不支持行级锁,只能对整张表加锁,读取时会对需要读到的所有表加共享锁,写入时则对表加排它锁。但在表有读取操作的同时,也可以往表中插入新的记录,这被称为并发插入(CONCURRENT INSERT)。

MyISAM 会在磁盘上存储三个文件,文件名和表名相同,扩展名分别是 .frm(存储表定义).MYD(MYData,存储数据)MYI(MyIndex,存储索引)。这里需要特别注意的是 MyISAM 只缓存索引文件,并不缓存数据文件。

数据库所在主机如果宕机,MyISAM 的数据文件容易损坏,而且难以恢复。

增删改查性能方面:SELECT 性能较高,适用于查询较多的情况

查看数据库引擎

在我们的数据库中输入

show engines;

可以查看当前MySQL支持的引擎和默认引擎

在这里插入图片描述

若需要创建指定引擎的数据库表,则可以在create语句后增加ENGINE指令即可

create table test(id int(10),name varchar(20)) engine = MyISAM;

不指定则默认使用InnoDB引擎。

功能 MYISAM INNODB
事务支持 不支持 支持
数据行锁定 不支持 支持
外键约束 不支持 支持
全文索引 支持 不支持
表空间的大小 较小 较大,约为MYISAM2倍

千言万语一句话,MyISAM节省空间,速度快,InnDB安全性好,有事务。

那什么是事务,这里插一句

事务

谈到事务大家一定要想到ACID,谈数据库不说ACID那就是耍流氓,ACID是啥,不就是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)

事务是什么,事务就是一个不可分割的数据库操作序列,也是数据库并发控制的基本单位,其执行的结果必须使数据库从一种一致性状态变到另一种一致性状态。事务是逻辑上的一组操作,要么都执行,要么都不执行

四个条件ACID

  • **原子性(Atomicity):**原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
  • **一致性(Consistency):**事务前后数据的完整性必须保持一致。
  • **隔离性(isolation):**事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
  • **持久性(durability):**持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

既然讲到隔离性,就来扯扯数据库的隔离级别

了解数据库隔离级别之前我们要先了解

什么是脏读?幻读?不可重复读?

  • 脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。
  • 不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。
  • 幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。

不可重复度和幻读的主要区别是,不可重复读的重点是修改,幻读的重点在于新增或者删除

数据库的隔离级别

  1. 未提交读,事务中发生了修改,即使没有提交,其他事务也是可见的,比如对于一个数A原来50修改为100,但是我还没有提交修改,另一个事务看到这个修改,而这个时候原事务发生了回滚,这时候A还是50,但是另一个事务看到的A是100.可能会导致脏读、幻读或不可重复读
  2. 提交读,对于一个事务从开始直到提交之前,所做的任何修改是其他事务不可见的,举例就是对于一个数A原来是50,然后提交修改成100,这个时候另一个事务在A提交修改之前,读取的A是50,刚读取完,A就被修改成100,这个时候另一个事务再进行读取发现A就突然变成100了;可以阻止脏读,但是幻读或不可重复读仍有可能发生
  3. 可重复读,就是对一个记录读取多次的记录是相同的,比如对于一个数A读取的话一直是A,前后两次读取的A是一致的;可以阻止脏读和不可重复读,但幻读仍有可能发生。
  4. 可串行化读,在并发情况下,和串行化的读取的结果是一致的,没有什么不同,比如不会发生脏读和幻读;该级别可以防止脏读、不可重复读以及幻读。
隔离级别 脏读 不可重复读 幻读
READ-UNCOMMITTED
READ-COMMITTED ×
REPEATABLE-READ × ×
SERIALIZABLE × × ×

MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)。

这里需要注意的是:与 SQL 标准不同的地方在于InnoDB 存储引擎在 REPEATABLE-READ(可重读)事务隔离级别 下使用的是Next-Key Lock 锁算法,因此可以避免幻读的产生,这与其他数据库系统(如 SQL Server)是不同的。所以 说InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读) 已经可以完全保证事务的隔离性要 求,即达到了 SQL标准的SERIALIZABLE(可串行化)隔离级别。

因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是READ-COMMITTED(读取提交内 容):,但是你要知道的是InnoDB 存储引擎默认使用 REPEATABLE-READ(可重读)并不会有任何性能损失

InnoDB 存储引擎在分布式事务 的情况下一般会用到SERIALIZABLE(可串行化)隔离级别。

索引

索引概述

所有的 MySQL 类型都可以进行索引,对相关列使用索引是提高 SELECT 查询性能的最佳途径。

先看两个常用的存储引擎实现索引的方式

InnoDB索引与MyISAM索引

InnoDB用的是聚簇索引(jù cù suǒ yǐn),而MyISAM用的是非聚簇索引,看了很多博客,有些都讲的太专业,很难理解,其实将数据存储与索引放在一起的就叫聚簇索引,就好查字典的时候,要查的内容和页码在一起,找到了索引就找到了数据。非聚簇索引就是讲数据和索引分开存储的。

了解了聚簇索引和非聚簇索引的区别以后,再来看这两个存储类型的底层,实际上两个存储类型的索引都是通过B树中的B+树实现的,只不过是实现的方式有所不同。

InnoDB&MyISAM实现BTree索引的区别

  • InnoDB,其数据文件本身就是索引文件,相比MyISAM,索引文件和数据文件是分离的其表数据文件本身就是按B+Tree组织的一个索引结构,树的节点data域保存了完整的数据记录,这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。这被称为“聚簇索引”或者聚集索引,而其余的索引都作为辅助索引,辅助索引的data域存储相应记录主键的值而不是地址,这也是和MyISAM不同的地方,在根据主索引搜索时,直接找到key所在的节点即可取出数据;在根据辅助索引查找时,则需要先取出主键的值,在走一遍主索引。因此,在设计表的时候,不建议使用过长的字段为主键,也不建议使用非单调的字段作为主键,这样会造成主索引频繁分裂。

  • MyISAM,B+Tree叶节点的data域存放的是数据记录的地址,在索引检索的时候,首先按照B+Tree搜索算法搜索索引,如果指定的key存在,则取出其data域的值,然后以data域的值为地址读区相应的数据记录,这被称为“非聚簇索引”

一下讲了这么多索引,那到底有多少种?这里一并列出

MySQL中主要有以下索引

  • 全局索引(FULLTEXT):全局索引,目前只有 MyISAM 引擎支持全局索引,它的出现是为了解决针对文本的模糊查询效率较低的问题,并且只限于 CHAR、VARCHAR 和 TEXT 列。

  • 哈希索引(HASH):哈希索引是 MySQL 中用到的唯一 key-value 键值对的数据结构,很适合作为索引。HASH 索引具有一次定位的好处,不需要像树那样逐个节点查找,但是这种查找适合应用于查找单个键的情况,对于范围查找,HASH 索引的性能就会很低。默认情况下,MEMORY 存储引擎使用 HASH 索引,但也支持 BTREE 索引。

  • B-Tree 索引:B 就是 Balance 的意思,BTree 是一种平衡树,它有很多变种,最常见的就是 B+ Tree,它被 MySQL 广泛使用。

  • R-Tree 索引:R-Tree 在 MySQL 很少使用,仅支持 geometry 数据类型,支持该类型的存储引擎只有MyISAM、BDb、InnoDb、NDb、Archive几种,相对于 B-Tree 来说,R-Tree 的优势在于范围查找。

那为什么要使用索引?

1、通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性

2、可以大大加快数据的检索速度,这也是创建索引的最主要的原因

3、帮助服务器避免排序和临时表

4、将随机IO变为顺序IO

5、可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义

索引可以在创建表的时候创建,也可以单独创建

索引为什么能提高查询速度?

DB在执行一条Sql语句的时候,默认的方式是根据搜索条件进行全表扫描,遇到匹配条件的就加入搜索结果集合。如果我们对某一字段增加索引,查询时就会先去索引列表中一次定位到特定值的行数,大大减少遍历匹配的行数,所以能明显增加查询的速度。

MySQL官方对于索引的定义为:索引是帮助MySQL高效获取数据的数据结构。即可以理解为:索引是数据结构。

索引拓展阅读(B-Tree&B+ Tree等):

http://blog.codinglabs.org/articles/theory-of-mysql-index.html

数据库范式

范式是具有最小冗余的表结构,3范式如下

第一范式(1NF)

第一范式:确保每列的原子性,每列都是不可再分的最小数据单元(也称为最小的原子单元),则满足第一范式(1NF)

在这里插入图片描述

第二范式(2NF)

第二范式:首先满足第一范式,并且表中的主键列不存在对主键的部分依赖,要求每个表只描述一件事情。
在这里插入图片描述

第三范式(3NF)

第三范式:满足第二范式,并且表中不存在对非主键列的传递依赖,出主键订单编号外,顾客姓名依赖于非主键顾客编号。

在这里插入图片描述

MySQL&锁不得不说的事

在这里插入图片描述

在关系型数据库中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎)、表级锁(MYISAM引擎)和页级锁(BDB引擎 )。

MyISAM和InnoDB存储引擎使用的锁:

  • MyISAM采用表级锁(table-level locking)。
  • InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁

行锁&表锁&页级锁

行锁

行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大。行级锁分为共享锁 和 排他锁。

特点:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

表锁

表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MYISAM与INNODB都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁)。

特点:开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低。

页级锁

页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。

特点:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

从锁的类型又可以分为:

共享锁&排它锁

共享锁

又叫做读锁。 当用户要进行数据的读取时,对数据加上共享锁。共享锁可以同时加上多个。

排他锁

又叫做写锁。 当用户要进行数据的写入时,对数据加上排他锁。排他锁只可以加一个,他和其他的排他锁,共享锁都相斥。

tips:

这两个锁什么时候加什么时候不能加很简单,就像你去住酒店(模拟用户操作数据行为),你可以看房(读锁),也可以住房(写锁),你在看房的时候(你加读锁,别人也可以加读锁),别人也能来跟你一起看(多个共享锁同时加),但是如果你住一晚上(加写锁),别人不能跟你一起住(排它锁只能加一个)。

数据库中的乐观锁&悲观锁

悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。在查询完数据的时候就把事务锁起来,直到提交事务。实现方式:使用数据库中的锁机制

乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。在修改数据的时候把事务锁起来,通过version的方式来进行锁定。实现方式:一般会使用版本号机制或CAS算法实现。

使用场景:读多写少(乐观锁),写多(悲观锁)。

有没有死锁?当然有

有资源,有人用,那就有可能会产生死锁。

死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方的资源,从而导致恶性循环的现象。

常见的解决死锁的方法

1、如果不同程序会并发存取多个表,尽量约定以相同的顺序访问表,可以大大降低死锁机会。

2、在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生概率;

3、对于非常容易产生死锁的业务部分,可以尝试使用升级锁定颗粒度,通过表级锁定来减少死锁产生的概率;

产生原因和解决方案实例拓展:

https://blog.csdn.net/tr1912/article/details/81668423

MySQL基础语法

(真的不是凑字数)

mysql -uroot -proot  -- 连接数据库
exit;  -- 退出连接

update mysql.user set authentication=PASSWORD('yourpassword') where user='root'; -- 修改root密码
flush privileges;  -- 刷新权限

-- 所有的语句都使用;结尾
show databases;  -- 查询数据库列表
use school;    -- 切换数据库 use 数据库名

show tables;  -- 查询数据库中所有的表
describe student; -- 显示数据库中所有的表的信息

create database westos; -- 创建数据库

对库的操作

创建库		
		CREATE  DATABASE  [IF NOT EXISTS] 库名
[DEFAULT] CHARACTER SET 字符名 |  [DEFAULT] COLLATE 校对规则 

这里初学者推荐下一个数据库可视化软件,比如Navicat for mysql,sqlyog等,都是有可视化操作数据库的,但是这些常用的操作指令是一定要掌握的

查看库
	SHOW DATABASES
	SHOW CREATE DATABASE 库名【查看数据库创建时的详细信息】
删除库
	DROP DATABASE  [IF EXISTS]  库名 
修改库
	ALTER  DATABASE  [IF NOT EXISTS] 库名
	[DEFAULT] CHARACTER SET 字符名   | [DEFAULT] COLLATE 校对规则
备份库中的数据和
	mysqldump -u 用户名 -p 数据库名 > 文件名.sql【window命令】
	Source 文件名.sql【在库下执行】

	mysql -uroot -p mydb1<c:\test.sql  (window命令)

对表的操作

增加表
		CREATE TABLE 表名(      列名    类型          )
修改表
	ALTER TABLE 表名
		ADD ( 列名  数据类型 );
	ALTER TABLE 表名
  		MODIFY( 列名  数据类型 );
查看表
		SHOW TABLES;
		SHOW CREATE TABLE 表名【查看表的创建细节】
		DESC 表名【查看表的结构】
删除表
		ALTER TABLE表名 
		DROP(列名);

对表中数据操作

	增加
		INSERT INTO 表名 ( 列名..)  VALUES  (数据..);
	修改
		UPDATE  表名  SET 列名=.. , 列名=WHERE=条件 ;
	删除
		DELETE FROM 表名  WHERE=条件;
		TRUNCATE TABLE【先摧毁整张表,再创建表结构】
	查看
		SELECT 列名
        FROM 表名,
        WHERE 条件,
        GROUP BY 列名,
        HAVING BY,
        ORDER BY 列名

常见题目

https://blog.csdn.net/ThinkWon/article/details/104778621

猜你喜欢

转载自blog.csdn.net/weixin_43876186/article/details/108535197