关系型数据库 - Mysql

21世纪互联网最重要的的是什么,当然是数据了,不然大数据个行业就没有意义了,数据保存就成为了一个比较重要的过程,目前市面上存储数据的都是用数据库,数据库又分关系型和非关系型,这里就不多阐述了,现在就说说关系型数据库MySQL。

Mysql由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的[关系型数据库之一,在 WEB 应用方面,MySQL是最好的 [RDBMS]应用软件之一。MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。MySQL所使用的 SQL 语言是用于访问[数据库]最常用标准化语言。MySQL 软件采用了双授权政策,分为社区版和商业版,由于其体积小、速度快、总体拥有成本低,尤其是[开放源码]一特点,一般中小型网站的开发都选择 MySQL 作为网站数据库。

以上这段来自百度百科。

Mysql架构图

在这里插入图片描述
**连接器:**连接器负责跟客户端建立连接、获取权限、维持和管理连接

**缓存查询:**查询缓存情况,命中缓存就使用缓存

**分析器:**分析语法,是否合法,是否命中缓存

**优化器:**优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联 (join)的时候,决定各个表的连接顺序

**执行器:**执行前判断使用,调用存储引擎返回结果。

事务

在操作数据库的过程中,难免要用到事务,因为我们避免不了要多数据进行一连串的操作,这个就关系到了事务的四大特性了。原子性(Atomicity),一致性(Consistency),隔离性(Isolation),持久性(Durability)。简称ACID,英文首字母。

**原子性:**一个事务是一个不可分割的操作集合,其中的操作要么一起完成,要么一起失败,只要其中一个操作失败,所有的操作都将无效,要回滚到事务前的状态。

**一致性:**执行一个事务之后,事务数据从一个状态向另一个状态的转变。

**持久性:**事务一旦提交,数据就永久修改。

**隔离性:**事务与事务之间互不干扰。

SQL语言一共分为4大类:数据定义语言DDL(Data Definition Language),数据操纵语言DML(Data Manipulation Language),数据查询语言DQL(Data Query Language),数据控制语言DCL(Data Control Language)。

在MySQL中,存在一些特殊的命令,如果在事务中执行了这些命令,会马上强制执行commit提交事务;如DDL语句(create table/drop table/alter/table)、lock tables语句等等。

不过,常用的DQL(select),DML(insert、update和delete)命令,都不会强制提交事务。

如何实现事务四大特性

mysql为了实现四大特性,利用到undo log,redo log,锁,MVVC等技术工具。

**原子性实现原理:**当事务对数据库数据进行修改时,InnoDB会生成对应的undo log,如果事务执行失败或调用了rollback,事务就会回滚,利用undo log中的信息回滚到事务之前的状态。

undo log 属于逻辑日志,记录sql执行的相关信息,当发生回滚时,Innodb会根据undo log的内容做与之前相反的工作。

**持久性实现原理:**通过redo log 记录操作,在事务提交时,对数据进行刷盘。

redo log 与缓冲池,redo log采用的是WAL(Write-ahead logging,预写式日志),所有修改先写入日志,再更新到缓冲池,保证了数据不会因MySQL宕机而丢失,从而满足了持久性要求。redo log 也需要在事务提交时将日志写入磁盘。
在这里插入图片描述
除了undo log、redo log,还有一个日志信息就是bin log。mysql-binlog是MySQL数据库的二进制日志,用于记录用户对数据库操作的SQL语句((除了数据查询语句)信息。可以使用mysqlbin命令查看二进制日志的内容。

隔离性

mysql的隔离性是指多个事务操作数据时,是相互隔离,互不干扰的。事务的隔离性与性能,效率其实是起到一个反作用力的效果。所以隔离性是分离级别,在对数据要求比较苛刻的情况下,必然要损耗性能与效率来保证数据的可靠性和有效性。所以就有了事务的四大隔离级别,分别是读未提交、读提交、可重复读、串行化。

当多个事务同时提交时,可能会出现脏读,不可重复读,幻读。

**脏读:**就是数据脏了,我们怎么知道这个数据脏了,就是在读取的时候发现我的数据跟我本来要查的不一样,也就是说本来查数据库的数据是0,但是刚好另一个事务将这个数据改成了1,把这个1给查出来了,另一个事务是在途中,所以就是我本来在查数据的过程中,查到了在途的事务中新增、修改或删除的数据,这就是代表数据脏了,这就是脏读。

**幻读:**很多时候会把脏读和幻读搞混,幻读,顾名思义,幻,迷幻,好像的意思,幻读是其他事务都提交了,自己还没提交,再次读数据的时候,没有把别人事务修改后的数据查出来了,好像数据丢了或突然多了、变了。

**不可重复读:**一个事务中同样的查询查询了两次,上一次读取的数据和下一次读取的数据不一致,两次查询中间有其他修改数据事务提交了导致的。就是其他事务已完成,当前事务还未结束,当前事务读取了已完成事务的内容。

总结:脏读是A事务读取还未提交的B事务的内容,幻读是A事务未读取已提交B事务的内容,不可重复读是A事务读取了已提交B事务的内容

接下来解释一下四大隔离界别。

**读未提交(Read Uncommit):**事务之间能相互读取未提交的内容;

**读提交(Read Commit):**事务之间只能读取已提交的内容;

**可重复读(Repeatable Read):**在当前事务中,只能读取当前事务开启的一瞬间的数据,直至当前事务结束。

**串行化(Serializable):**当前事务在读取或修改数据时,其他事务必须等我结束才能执行,就得排着队,跟个冰糖葫芦串一样。

隔离性追求的是并发情形下事务之间互不干扰。我们主要考虑最简单的读操作和写操作(加锁读等特殊读操作会特殊说明),那么隔离性的探讨,主要可以分为两个方面:

  • (一个事务)写操作对(另一个事务)写操作的影响:锁机制保证隔离性
  • (一个事务)写操作对(另一个事务)读操作的影响:MVCC保证隔离性

锁机制我们常听到的有行锁和表锁。

按照锁的粒度来说,锁可以分为表锁、行锁以及其他位于两者之间的锁。

表锁就是在操作数据时会锁住整张表,并发性能差。

行锁只需要锁定操作数据行,并发性能好。

加锁的过程是比较消耗资源的(获取锁、检查锁、释放锁等)

如何查看InnoDB锁信息:

#查看锁情况

select * from information_schema.innodb_locks;

#查看InnoDB整体状态,其中包括锁的情况

show engine innodb status;

MVVC (Multi-Version Concurrency Control) (注:与MVCC相对的,是基于锁的并发控制,Lock-Based Concurrency Control)是一种基于多版本的并发控制协议,只有在InnoDB引擎下存在。MVCC是为了实现事务的隔离性,通过版本号,避免同一数据在不同事务间的竞争,你可以把它当成基于多版本号的一种乐观锁。当然,这种乐观锁只在事务级别提交读和可重复读有效。MVCC最大的好处,相信也是耳熟能详:读不加锁,读写不冲突。在读多写少的OLTP应用中,读写不冲突是非常重要的,极大的增加了系统的并发性能。

MVCC最大的优点是读不加锁,因此读写不冲突,并发性能好。InnoDB实现MVCC,多个版本的数据可以共存,主要基于以下技术及数据结构:

1)隐藏列:InnoDB中每行数据都有隐藏列,隐藏列中包含了本行数据的事务id、指向undo log的指针等。

2)基于undo log的版本链:前面说到每行数据的隐藏列中包含了指向undo log的指针,而每条undo log也会指向更早版本的undo log,从而形成一条版本链。

3)ReadView:通过隐藏列和版本链,MySQL可以将数据恢复到指定版本;但是具体要恢复到哪个版本,则需要根据ReadView来确定。所谓ReadView,是指事务(记做事务A)在某一时刻给整个事务系统(trx_sys)打快照,之后再进行读操作时,会将读取到的数据中的事务id与trx_sys快照比较,从而判断数据对该ReadView是否可见,即对事务A是否可见。

trx_sys中的主要内容,以及判断可见性的方法如下:

  • low_limit_id:表示生成ReadView时系统中应该分配给下一个事务的id。如果数据的事务id大于等于low_limit_id,则对该ReadView不可见。
  • up_limit_id:表示生成ReadView时当前系统中活跃的读写事务中最小的事务id。如果数据的事务id小于up_limit_id,则对该ReadView可见。
  • rw_trx_ids:表示生成ReadView时当前系统中活跃的读写事务的事务id列表。如果数据的事务id在low_limit_id和up_limit_id之间,则需要判断事务id是否在rw_trx_ids中:如果在,说明生成ReadView时事务仍在活跃中,因此数据对ReadView不可见;如果不在,说明生成ReadView时事务已经提交了,因此数据对ReadView可见。
    在这里插入图片描述
    事务快照是用来存储数据库的事务运行情况。一个事务快照的创建过程可以概括为:
  1. 查看当前所有的未提交并活跃的事务,存储在数组中
  2. 选取未提交并活跃的事务中最小的XID,记录在快照的xmin中
  3. 选取所有已提交事务中最大的XID,加1后记录在xmax中

Read View (主要是用来做可见性判断的):创建一个新事务时,copy一份当前系统中的活跃事务列表。意思是,当前不应该被本事务看到的其他事务id列表。

对于Read View快照的生成时机,也非常关键,正是因为生成时机的不同,造成了RC,RR两种隔离级别的不同可见性;

  1. 在innodb中(默认repeatable read级别),事务在begin/start transaction之后的第一条select读操作后,会创建一个快照(Read View),将当前系统中活跃的其他事务记录记录起来
  2. 在innodb中(默认repeatable committed级别),事务中每条select语句都会创建一个快照(Read View)

猜你喜欢

转载自blog.csdn.net/jianghuafeng0/article/details/108767053