MySql知识总结

MySql 技术内幕

本博客记录mysql的一些知识点和高级用法:

  • 存储引擎
  • 事务隔离等级
  • 使用mysql 做为Hive的metastore

###存储引擎
1.InnoDB 存储引擎:

InnoDB 存储引擎支持事务,其设计目标主要面向在线事务处理(OLTP)的应用。其特点是行锁设计,支持外键,并支持类似于Oracle的非锁定读,即默认读取操作不会产生锁。从Mysql数据库5.5.8版本开始,InnoDB存储引擎是默认的存储引擎。

2.MyISAM 存储引擎:

MyISAM存储引擎不支持事务,表锁设计,支持全文索引,主要面向一些联机分析处理(OLAP)数据库应用。在Mysql5.5.8版本之前MyISAM是默认的存储引擎(除Windows版本外)。

3.NDB 存储引擎:

NDB存储引擎是一个集群存储引擎,类似于Oracle的RAC集群,不过与Oracle RAC share everything架构不同的是,其结构是share nothing 的集群架构,因此能提供更高的可用性。NDB的特点是数据全部放在内存中(从Mysql 5.1版本开始,可以将非索引数据放在磁盘上),因此主键查找的速度极快,并且通过添加NDB数据存储节点(Data Node)可以现行地提高数据库性能,是高可用,高性能的集群系统。

4.Memory 存储引擎:

Memory 存储引擎(之前称为HEAP存储引擎)将表中的数据存放在内存中,如果数据库重启或发生崩溃,表中的数据都将消失。

5.Archive 存储引擎:

Archive 存储引擎只支持INSERT 和SELECT操作,从Mysql5.1 开始支持索引。Archive 存储引擎使用行锁来实现高并发的插入操作,但是其本身并不是事务安全的存储引擎,其设计目标主要是提供高速的插入和压缩功能。

6.Federated 存储引擎:

Federated存储引擎表并不存放数据,它只是指向一台远程Mysql数据库服务器上的表。

7.Maria 存储引擎:

Maria 存储引擎是新开发的引擎,设计目标主要是用来取代原有的MyISAM存储引擎,从而称为Mysql的默认存储引擎。特点是:支持缓存数据和索引文件,应用行锁设计,提供了多版本并发控制(MVCC)功能,支持事务和非事务安全的选项,以及更好的BLOB字符类型的处理性能。

###事务隔离等级

Mysql的事务隔离等级分为4大类:读取未提交内容,读取提交内容,可重复读,可串行化

1.读取未提交内容 Read Uncommitted:

所有事务都可以看到其他未提交事务的执行结果
首先,修改隔离级别,查看全局隔离级别使用: select @@global.tx_isolation;

set tx_isolation='READ-UNCOMMITTED';
select @@tx_isolation;
+------------------+
| @@tx_isolation   |
+------------------+
| READ-UNCOMMITTED |
+------------------+

--事务A:启动一个事务
start transaction;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |    1 |
|    2 |    2 |
|    3 |    3 |
+------+------+

--事务B:也启动一个事务(那么两个事务交叉了)
--在事务B中执行更新语句,且不提交
start transaction;
update tx set num=10 where id=1;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |   10 |
|    2 |    2 |
|    3 |    3 |
+------+------+

--事务A:那么这时候事务A能看到这个更新了的数据吗?
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |   10 |   --->可以看到!说明我们读到了事务B还没有提交的数据
|    2 |    2 |
|    3 |    3 |
+------+------+

--事务B:事务B回滚,仍然未提交
rollback;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |    1 |
|    2 |    2 |
|    3 |    3 |
+------+------+

--事务A:在事务A里面看到的也是B没有提交的数据
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |    1 |      --->脏读意味着我在这个事务中(A中),事务B虽然没有提交,但它任何一条数据变化,我都可以看到!
|    2 |    2 |
|    3 |    3 |
+------+------+

2.读取提交内容 Read Committed

这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)
它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变
这种隔离级别出现的问题是——不可重复读(Nonrepeatable Read):不可重复读意味着我们在同一个事务中执行完全相同的select语句时可能看到不一样的结果。
导致这种情况的原因可能有:(1)有一个交叉的事务有新的commit,导致了数据的改变;(2)一个数据库被多个实例操作时,同一事务的其他实例在该实例处理其间可能会有新的commit

--首先修改隔离级别
set tx_isolation='read-committed';
select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+

--事务A:启动一个事务
start transaction;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |    1 |
|    2 |    2 |
|    3 |    3 |
+------+------+

--事务B:也启动一个事务(那么两个事务交叉了)
--在这事务中更新数据,且未提交
start transaction;
update tx set num=10 where id=1;
select * from tx;
+------+------+
| id   | num  |
+------+------+
|    1 |   10 |
|    2 |    2 |
|    3 |    3 |
+------+------+

--事务A:这个时候我们在事务A中能看到数据的变化吗?
select * from tx; --------------->
+------+------+                
| id   | num  |                
+------+------+                
|    1 |    1 |--->并不能看到!  
|    2 |    2 |                
|    3 |    3 |                
+------+------+                |——>相同的select语句,结果却不一样
                                  
--事务B:如果提交了事务B呢?            
commit;                           
                                  
--事务A:                          
select * from tx; --------------->
+------+------+
| id   | num  |
+------+------+
|    1 |   10 |--->因为事务B已经提交了,所以在A中我们看到了数据变化
|    2 |    2 |
|    3 |    3 |
+------+------+

3.可重复读 Repeatable Read:

这是MySQL的默认事务隔离级别
它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行
此级别可能出现的问题——幻读(Phantom Read):当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。
一个事务必须在commit后才能看到别的事务提交的数据,这时若commit,那么很可能会出现插入异常(插入了同样的行导致主键重复)。

--事务A:
set tx_isolation = 'repeatable-read';
start transaction;
select * from d;
+----+------+
| id | v    |
+----+------+
|  1 | a    |
|  2 | a    |
+----+------+

--事务B:
set tx_isolation = 'repeatable-read';
start transaction;
select * from d;
+----+------+
| id | v    |
+----+------+
|  1 | a    |
|  2 | a    |
+----+------+

--事务A:
insert into d values(3, "d");
commit;
select * from d;
+----+------+
| id | v    |
+----+------+
|  1 | a    |
|  2 | a    |
|  3 | d    |
+----+------+

--事务B:
select * from d;
+----+------+
| id | v    |
+----+------+
|  1 | a    |
|  2 | a    |
+----+------+
insert into d values(3, "d");
--ERROR 1062 (23000): Duplicate entry '3' for key 'PRIMARY'
--这里出现的问题就是“幻读”,如果出现这种问题想要解决可以在更改之前做一次commit。
commit;
select * from d;
+----+------+
| id | v    |
+----+------+
|  1 | a    |
|  2 | a    |
|  3 | d    |
+----+------+

4.可串行化 Serializable:

这是最高的隔离级别
它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。
在这个级别,可能导致大量的超时现象和锁竞争
在该事务隔离级别下面,当有插入,更新和删除操作时必须等待其他事务提交才能执行。

--事务A
set tx_isolation = 'serializable';
select * from d;
+----+------+
| id | v    |
+----+------+
|  1 | a    |
|  2 | a    |
|  3 | d    |
|  4 | e    |
+----+------+

--事务B:
set tx_isolation = 'serializable';
select * from d;
+----+------+
| id | v    |
+----+------+
|  1 | a    |
|  2 | a    |
|  3 | d    |
|  4 | e    |
+----+------+

--事务A:
insert into d values(5,"f");
..查询等待一直不出现结果

--事务B:
commit;

--事务A:
insert into d values(5,"f");
Query OK, 1 row affected (46.36 sec) --发现在事务A中过了46s才处理完成

--事务B:
update d set v = 'g' where id = 4;
..查询等待一直不出现结果

--事务A:
commit;

--事务B:
update d set v = 'g' where id = 4;
Query OK, 1 row affected (45.83 sec)--发现在事务B中同样的事情发生了,在事务A中新插入的数据并未提交,必须等待事务A commit提交后才执行更新操作

###使用mysql 做为Hive的metastore

使用mysql作为Hive的元数据库:

-- 在mysql中创建一个用户并赋予权限
grant all privileges on *.* to hive@"%" identified by "hive";
flush privileges;

###在mysql8.0 以后创建用户并授予权限:

create user test@"%" identified by "test@2018";
grant all PRIVILEGES on *.* to test@"%";
FLUSH PRIVILEGES;

你可能感兴趣的:(Mysql)