MySql 基础概念全面讲解(一)

MySql 基础概念全面讲解(一)

数据库的基本概念

磁盘文件–> 层次模型 –> 网状模型 –> (Codd) 关系模型
主键(Primary key):用于惟一确定一个记录的字段;复合主键:多个字段组合成一个主键(NOT NULL);

惟一键:一个或多个字段的组合,填入的数据必须能在本表 中唯一标识本行;允许为NULL,但只能有一个null。

约束:

  • 主键约束:惟一、非空;一张表只能有一个;
  • 惟一键约束:惟一,可以存在多个;
  • 外键约束:参考性约束;
  • 检查性约束:check;

三层模型:

  • 物理层 –> SA (决定数据的存储格式,即RDBMS在磁盘上如何组织文件)
  • 逻辑层 –> DBA(描述存储什么数据,以及数据间存在什么样的关系)
  • 视图层 –> Coder(描述DB中的部分数据)

事务: 多个操作被当作一个整体对待 ACID: 原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。

三范式:设计关系数据库时,遵从不同的规范要求,设计出合理的 关系型数据库,这些不同的规范要求被称为不同的范式,各种范 式呈递次规范,越高的范式数据库冗余越小。

目前关系数据库有六种范式:第一范式(1NF)、第二范式 (2NF)、第三范式(3NF)、巴德斯科范式(BCNF)、第 四范式(4NF)和第五范式(5NF,又称完美范式)。满足最 低要求的范式是第一范式(1NF)。在第一范式的基础上进 一步满足更多规范要求的称为第二范式(2NF),其余范式 以次类推。一般说来,数据库只需满足第三范式(3NF)即可。
范式:第一范式、第二范式、第三范式;

  • 1NF:无重复的列,每一列都是不可分割的基本数据项,同一列中不能有多个值
  • 2NF:属性完全依赖于主键,第二范式必须先满足第一范式 ,要求表中的每个行必须可以被唯一地区分。
  • 3NF:属性不依赖于其它非主属性,满足第三范式必须先满足第二范式。第三范式要求一个数据库表中不包含已在其它表中已包含的非主关键字信息,非PK的字段间不能有从属关系。

三范式详解:https://www.zhihu.com/question/24696366

MySql基础操作

远程连接操作

  • 链接数据库:mysql -h localhost -u root -p ,回撤后输入密码,默认端口为3306
  • 连接数据库2:mysql -h localhost -P3306 -uUserName -pPassword;-u和userNmae之间没有空格,-p与password之间也没有空格
  • 显示但前数据库列表: SHOW DATABASES;
  • 显示库中的表:1.指定库名:mysql>use 库名; 2.显示表:mysql>show tables;
  • 显示表结构:describe 表名;

表操作

  • 修改表名:ALTER TABLE class_info2 RENAME class_info;
  • 添加列:ALTER TABLE class_info ADD phone varchar(11);
  • 修改列的数据结构:ALTER TABLE class_info MODIFY phone int;
  • 使用mobile char(11)替换phone这一列:ALTER TABLE class_info CHANGE COLUMN phone mobile char(11);
  • 删除某一个列:ALTER TABLE class_info DROP COLUMN mobile;
  • 查看表结构:SHOW INDEXES FROM class_info;

索引

  • 创建索引: CREATE INDEX index_name ON table_name (index_col_name,…);
  • 删除索引: DROP INDEX index_name ON table_name;
  • 查看索引: SHOW INDEXES FROM table_name;
  • 唯一索引: CREATE UNIQUE INDEX unindex_indexName ON table_name(column_name);
  • 添加唯一索引:ALTER TABLE class_info ADD UNIQUE KEY(classcun);
  • 添加索引:ALTER TABLE class_info ADD INDEX(classcun);

注意,唯一索引列的值可以为null,但是只能有一个null。

属性操作

  • 查看有多少用户在链接中:show processlist;

show variables like ‘%slow%’;

show variables like “%quer%”;

MySql存储引擎

查看当前数据库中表使用的存储引擎:SHOW TABLE STATUS;
查看MqSql所有的存储引擎:SHOW ENGINES; 可以看到support中有一个default表示当前默认使用的引擎。

查看InnoDB存储引擎的状态信息:SHOW ENGINE innodb STATUS;
查看用户授权:查看授权: SHOW GRANTS [FOR ‘user’@’host’]

InnoDB与MyISAM

innodb 的主索引文件上 直接存放该行数据,称为聚簇索引,次索引指向对主键的引用
myisam 中, 主索引和次索引,都指向物理行(磁盘位置).称为堆组织表。

innodb:

  1. 主键索引 既存储索引值,又在叶子中存储行的数据
  2. 如果没有主键, 则会 Unique key 做主键
  3. 如果没有 unique,则系统生成一个内部的 rowid 做主键.
  4. 像 innodb 中,主键的索引结构中,既存储了主键值,又存储了行数据,这种结构称为”聚簇索引”

高性能索引策略:对于innodb而言,因为节点下有数据文件,因此节点的分裂将会比较慢. 对于innodb的主键,尽量用整型,而且是递增的整型. 如果是无规律的数据,将会产生的页的分裂,影响速度.

聚簇索引
优势: 根据主键查询条目比较少时,不用回行(数据就在主键节点下)
劣势: 如果碰到不规则数据插入时,造成频繁的页分裂.

MySql的日志

  • 查询日志:general_log
  • 慢查询日志:log_slow_queries
  • 错误日志:log_error, log_warnings
  • 二进制日志:binlog
  • 中继日志:relay_log
  • 事务日志:innod_log

事务

为了数据的一致性,使用事务。多个事务一起执行就会引发事务的隔离性的问题。要解决事务的隔离性问题就需要使用

事务:一组原子性的SQL查询、或者是一个或多个SQL语句组成的独立工作单元。
在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。

事务的特性

一般来说,事务是必须满足4个条件(ACID)::原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。

  • 原子性:整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
  • 一致性:在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。
  • 隔离性:两个事务的执行是互不干扰的,一个事务不可能看到其他事务运行时,中间某一时刻的数据。
  • 持久性:在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。

设置手动事务

查看事务类型:SELECT @@autocommit; //1为自动提交,0为手动提交
修改为手动提交:SET autocommit = 0;

事务过程

启动:START TRANSACTION
执行sql语句
提交:COMMIT 或 回滚:ROLLBACK

事务日志

  • innodb_log_files_in_group :一组的日志文件数量,至少2个;
  • innodb_log_group_home_dir
  • innodb_log_file_size :日志文件大小,默认为5M;可以调大此值;
  • innodb_mirrored_log_groups
  • innodb_flush_logs_at_trx_commit:
    • 0:log buffer(内存)每秒一次同步到log file中,且同时会进行log file到data file的同步操作;
    • 1:每次提交时,log buffer同步到log file,同时进行log file到data file的同步操作;
    • 2:每次提交时,log buffer同步到log file,但不会同时进行log file到data file的同步操作;

事务的隔离性

事务是好的,但是事务又会带来其他问题,比如:脏读、不可重复读和幻影读等问题。

查看数据库的默认隔离级别:SELECT @@session.tx_isolation;//默认为REPEATABLE-READ

  • READ-UNCOMMITTED:未提交读
    事务中的修改,即使没有提交,对其它事务也是可见的,也称为脏读;
  • READ-COMMITTED:提交读(RC)
    一个事务中发生了两次读操作,第一次读操作和第二次读操作之间,另外一个事务对数据进行了修改并提交了,这时候两次读取的数据是不一致的,也称为不可重复读;
  • REPEATABLE-READ:可重复读(RR)
    第一个事务对一定范围的数据进行批量修改,第二个事务在这个范围增加一条数据,这时候第一个事务就会丢失对新增数据的修改,也称为幻读;
  • SERIALIZABLE:串行化; 不会出现任何问题。只能一个事务提交后,另外一个事务才能开始。最安全,但效率也是最差的。

针对以上可能的问题,InnoDB提供了四种不同级别的机制保证数据隔离性。
事务的隔离用是通过锁机制实现的,不同于MyISAM使用表级别的锁,InnoDB采用更细粒度的行级别锁,提高了数据表的性能。InnoDB的锁通过锁定索引来实现,如果查询条件中有主键则锁定主键,如果有索引则先锁定对应索引然后再锁定对应的主键(可能造成死锁),如果连索引都没有则会锁定整个数据表。

锁机制

需要解决事务的隔离性的问题,就需要使用到锁。

查看mysql锁状态 show status like ‘%lock%’;//关键看Innodb_row_lock_current_waits有多少在等待

读锁: 共享锁(S Lock)可被多个操作的共享。

在select后面加上LOCK IN SHARE MODE会在读取的行上加共享锁,其他session只能读不能修改或删除,如果有其他事务修改了记录,那么会等待事务提交后,再读取。

即在符合条件的rows上都加了共享锁,这样的话,其他人可以读取这些记录,也可以继续添加共享锁,但是无法修改这些记录直到你这个加锁的过程执行完成(完成的情况有:事务的提交,事务的回滚,否则直接锁等待超时)。

测试用例

//打开一个mysql链接:session1
SET autocommit = 0; //这里只是修改session1的事务提交改为手动提交,session2还是会自动提交。

begin ;
select * from class_info where id=2 LOCK IN SHARE MODE;
//commit;

//begin; //这里尝试多次对where id=2的行数据加锁。
//select * from class_info where id=2 LOCK IN SHARE MODE;
//

//再打开一个session2
update class_info set class_name='111' where id=2;

解说:id=2这条数据在session1中加了共享锁,这个时候所有事物只能读而不能写。
session2去修改了2这条数据,这个时候修改会处于等待中,等待过程中如果session1中的没有提交或者回滚,则session2中的update就会报lock请求超时。如果session2中修改的是where id=3则不会被锁住,说明lock in share mode锁的是行级别的。

上面对where id=2加了两次锁,只需要某一次的事务执行了提交,则该锁释放,说明共享锁不管加几次他们都是同一把锁,且只需要一次提交即可解锁。

写锁: 排它锁(X Lock),独占锁。

排他锁:表示对数据进行写操作,如果一个事务对对象加了排他锁,其他事务就不能再给它加任何锁了,
在select后面加上 FOR UPDATE 在读取行上设置一个排他锁,阻止其他session读取或者写入行数据。

对于update,insert,delete语句MySql会自动加排它锁.

表锁:操作对象是数据表。Mysql大多数锁策略都支持(常见mysql innodb),是系统开销最低但并发性最低的一个锁策略。事务t对整个表加读锁,则其他事务可读不可写,若加写锁,则其他事务增删改都不行。

行级锁:操作对象是数据表中的一行。是MVCC技术用的比较多的,但在MYISAM用不了,行级锁用mysql的储存引擎实现而不是mysql服务器。但行级锁对系统开销较大,处理高并发较好。

MVCC:多版本并发控制(MVCC,Multiversion Currency Control)。一般情况下,事务性储存引擎不是只使用表锁,行加锁的处理数据,而是结合了MVCC机制,以处理更多的并发问题。Mvcc处理高并发能力最强,但系统开销比最大(较表锁、行级锁),这是最求高并发付出的代价。

MVCC锁详解

InnoDB实现MVCC的方法是,它存储了每一行的三个(1)额外的隐藏字段,这三个隐藏字段分别记录了行的创建的时间和删除的时间。在每个事件发生的时候,每行存储版本号,而不是存储事件实际发生的时间。每次事物的开始这个版本号都会增加。自记录时间开始,每个事物都会保存记录的系统版本号。依照事物的 版本来检查每行的版本号。在事物隔离级别为可重复读的情况下,来看看怎样应用它。

  • SELECT的情况下确保他们符合两个标准:

    1. InnoDB只查找版本早于当前事务版本的数据行(也就是数据行的版本必须小于等于事务的版本),这确保当前事务读取的行都是事务之前已经存在的,或者是由当前事务创建或修改的行
    2. 行的删除操作的版本一定是未定义的或者大于当前事务的版本号。确定了当前事务开始之前,行没有被删除(这里的不是真正的删除数据,而是标志出来的删除。真正意义的删除是在commit的时候)
      符合了以上两点则返回查询结果。
  • INSERT的情况下:InnoDB为每个新增行记录当前系统版本号作为创建ID。

  • DELETE的情况下:InnoDB为每个删除行的记录当前系统版本号作为行的删除ID。
  • UPDATE的情况下:InnoDB复制了一行。这个新行的版本号使用了系统版本号。它也把系统版本号作为了删除行的版本。

注:隐藏的三个字段为:

  1. DB_TRX_ID:一个6byte的标识,每处理一个事务,其值自动+1,上述说到的“创建时间”和“删除时间”记录的就是这个DB_TRX_ID的值,如insert、update、delete操作时,删除操作用1个bit表示。 DB_TRX_ID是最重要的一个
  2. DB_ROLL_PTR: 大小是7byte,指向写到rollback segment(回滚段)的一条undo log记录(update操作的话,记录update前的ROW值)
  3. DB_ROW_ID: 大小是6byte,该值随新行插入单调增加,当由innodb自动产生聚集索引时,聚集索引包括这个DB_ROW_ID的值,不然的话聚集索引中不包括这个值. 这个用于索引当中。

MySQL的索引

索引:提取索引的创建在的表上字段中的数据,构建出一个独特的数据结构;
索引的作用:加速查询操作;副作用:降低写操作性能;
索引类型:B+ TREE,HASH,B- TREE
B+ TREE:顺序存储,每一个叶子结点到根结点的距离相同;左前缀索引,适合于范围类型的数据查询;

在MySQL中,InnoDB引擎表是(聚集)索引组织表(clustered index organize table),而MyISAM引擎表则是堆组织表(heap organize table)

聚集索引与堆组织表对比

聚集索引是一种索引组织形式,索引的键值逻辑顺序决定了表数据行的物理存储顺序;
而非聚集索引则就是普通索引了,仅仅只是对数据列创建相应的索引,不影响整个表的物理存储顺序。

聚集索引表里数据物理存储顺序和主键索引的顺序一致,所以如果新增数据是离散的,会导致数据块趋于离散,而不是趋于顺序。
而非聚集索表数据写入的顺序是按写入时间顺序存储的。

聚集索引表相比堆组织表的优势是:
范围查询效率更高;
数据频繁更新(聚集索引本身不更新)时,更不容易产生碎片;
特别适合有一小部分热点数据频繁读写的场景;
通过主键访问数据时快速可达;

查询走索引的情况

ALTER TABLE index_demo ADD INDEX(name,head_url,address);
#走索引
explain select * from index_demo where name='111' and head_url>'22' and address='222';

#走索引
explain select * from index_demo where name='111'  and address='222';

#走索引
explain select * from index_demo where name='111' and head_url>'22';

#全表扫描,使用覆盖索引type=index,using index
explain select * from index_demo where   head_url>'22';

#全表扫描,使用覆盖索引type=index,using index
explain select * from index_demo where  address='222';


#全表扫描,使用覆盖索引type=index,using index
explain select * from index_demo where   head_url>'22' and  address='222';

如果查询条件不是从最左侧列开始,索引无效;
index(age,Fname)
WHERE Fname=’Jerry’;//走索引,老版本不走索引,但是新版本innodb是走索引的。
WHERE age=30;//走索引
WHERE age>30 AND Fname=’Smith’; //走索引

不能跳过索引中的某列;
index(name,age,gender)
WHERE name=’black’ and age > 30;//走索引
WHERE name=’black’ AND gender=’F’;//不走索引
如果查询中的某个列是为范围查询,那么其右侧的列都无法再使用索引优化查询;WHERE age>30 AND name=’Smith’;(估计是老版本不走索引,但是新版本亲测会走索引,所以还是需要亲自上手测试一下)

Hash索引:基于哈希表实现,特别适用于值的精确匹配查询;

  • 适用场景:只支持等值比较查询,例如=, IN(), <=>
  • 不用场景:所有非精确值查询;MySQL仅对memory存储引擎支持显式的hash索引;

高性能索引策略:

  • 在WHERE中独立使用列,尽量避免其参与运算; 如,WHERE age+2 > 32 ;
  • 左前缀索引:索引构建于字段的最左侧的多少个字符,要通过索引选择性来评估索引选择性:不重复的索引值和数据表的记录总数的比值;
  • 多列索引:AND连接的多个查询条件更适合使用多列索引,而非多个单键索引;
  • 选择合适的索引列次序:选择性最高的放左侧;

explain来分析索引有效性:
EXPLAIN SELECT select_options
输出结果:

  • id:当前查询语句中,第个SELECT语句的编号;
  • select_type:查询类型:
  • table:查询针对的表;
  • type:关联类型,或称为访问类型,即MySQL如何去查询表中的行
    • ALL:全表扫描;
    • index:根据索引的顺序进行的全表扫描;但同时如果Extra列出现了”Using index”表示使用了覆盖索引;
    • range:有范围限制地根据索引实现范围扫描;扫描位置始于索引中的某一项,结束于另一项;
    • ref:根据索引返回的表中匹配到某单个值的所有行(匹配给定值的行不止一个);
    • eq_ref:根据索引返回的表中匹配到某单个值的单一行,仅返回一个行,但需要与某个额外的参考值比较,而不是常数;
    • const,system:与某个常数比较,且只返回一行;
  • possiable_keys:查询中可能会用到的索引;
  • key:查询中使用的索引;
  • key_len:查询中用到的索引长度;
  • ref:在利用key字段所显示的索引完成查询操作时所引用的列或常量值;
  • rows:MySQL估计出的为找到所有的目标项而需要读取的行数;
  • Extra:额外信息
    • Using index:使用了覆盖索引进行的查询;
    • Using where:拿到数据后还要再次进行过滤;
    • Using temporary:使用了临时表以完成查询;
    • Using filesort:对结果使用了一个外部索引排序;

MySQL:备份和恢复(数据)

1.导出整个数据库  
mysqldump -u 用户名 -p –default-character-set=latin1 数据库名 > 导出的文件名(数据库默认编码是latin1)  
mysqldump -u wcnc -p smgp_apps_wcnc > wcnc.sql  
2.导出一个表  
mysqldump -u 用户名 -p 数据库名 表名> 导出的文件名  
mysqldump -u wcnc -p smgp_apps_wcnc users> wcnc_users.sql  
3.导出一个数据库结构  
mysqldump -u wcnc -p -d –add-drop-table smgp_apps_wcnc >d:wcnc_db.sql  
-d 没有数据 –add-drop-table 在每个create语句之前增加一个drop table  
4.导入数据库  
A:常用source 命令  
进入mysql数据库控制台,  
如mysql -u root -p  
mysql>use 数据库  
然后使用source命令,后面参数为脚本文件(如这里用到的.sql)  
mysql>source wcnc_db.sql  
B:使用mysqldump命令  
mysqldump -u username -p dbname < filename.sql  
C:使用mysql命令  
mysql -u username -p -D dbname < filename.sql  

参考

http://blog.csdn.net/timchen525/article/details/75268151 慢查询日志开启
https://www.cnblogs.com/phpper/p/6937650.htmlMVCC

你可能感兴趣的:(mysql)