MySQL InnoDB存储引擎

呵呵哒。。。

 

MySQL体系结构和存储引擎

首先要搞懂的是什么是数据库,什么是数据库实例。

数据库:物理操作系统文件或其他形式文件类型的集合。

实例:MySQL数据库由后台线程以及一个共享内存区组成,实例才是真正对数据库进行操作的。

譬如:数据库就像盖楼所需的石头、砂和水泥等原材料,而正在使用这些原材料盖楼的施工队则是实例,哈哈。

 

MySQL实例启动的方法有很多种,启动时读取配置文件,如果配置文件有多个,而且配置项又有很多相同的,那么会以最后读到的配置项为准。

 

数据库实例是一层数据库管理软件,用户不能直接地操纵数据库,只能通过实例提供的接口来访问数据库。

psearch

图1 MySQL体系结构

从图1中可以发现,MySQL又一下几部分组成:

  • 连接池组件:Connectors
  • 管理服务和工具组件:Management Service & Utilities
  • SQL接口组件:SQL Interface
  • 查询分析器组件:Parser
  • 优化器组件:Optimizer
  • 缓冲组件:Caches & Buffers
  • 插件式存储引擎:Pluggable Storage Engines
  • 物理文件:Files & Logs

MySQL的这个架构模式在很多数据库中都有体现,你可以学一下MySQL这个架构,好歹也是架构啊!

MySQL数据库的特色就是插件式的表存储引擎。

MySQL插件式存储引擎架构提供了一系列标准的管理和服务支持。

存储引擎是底层物理结构的实现,每个存储引擎开发者可以按照自己的意愿进行开发。

    注意:

        存储引擎是基于表的,而不是数据库的!

 

存储引擎的好处是:

  • 每个存储引擎都有各自的特点,可以根据具体的应用不同选择/建立不同的存储引擎表。
  • 对于上层应用的开发来说,存储引擎是透明的。
  • MySQL数据库的核心在于存储引擎。
  • MySQL官方手册给出了编写自定义存储引擎的过程(可以去看下咯)。

 

常见的存储引擎有(不能详写了,木有时间了):

InnoDB、MyISAM、NDB、Memory、Archive、Federated、Maria;

其他的有:Merge、CSV、Sphinx、Infobright

至于存储引擎之间的比较,让他们见鬼去吧, 哦,我的上帝~

 

查看当前MySQL数据库所支持的引擎:SHOW ENGINES\G;

MySQL自带的示例数据库和数据库的文档放在一起,下载地址:http://dev.mysql.com/doc/

 

连接MySQL

连接MySQL操作是一个连接进程和MySQL数据库实例进行通信,本质上是进程通信(还好老子看了点,不然就懵逼了),常见的进程通信方式有:

管道、命名管道、命名名字、TCP/IP套接字、UNIX域套接字。

TCP/IP套接字:在任何平台下都可以使用,也是使用最多的一种,通过TCP/IP连接MySQL实例时,MySQL会先检查一张权限视图,判断请求客户端IP是否允许连接到实例;

SELECT host, user, password FROM user;

命名管道和共享内存:

UNIX域套接字:在Linux和Unix下可以使用UNIX域套接字,这个并不是一个网络协议,所以只能在客户端和数据库实例在同一台机器的情况下使用。

制定套接字文件的路径:—socket=/tmp/mysql.sock

SHOW VARIABLES LIKE 'socket';

 

好了,这章就看完了,遗留的就是对不同存储引擎的介绍和比较咯。。。。。。

 

 

InnoDB存储引擎

 

InnoDB是事物安全的MySQL存储引擎,是OLTP应用中核心表的首选存储引擎。

InnoDB是MySQL中第一个完整支持ACID事物的存储引擎,其特点是:

行锁设计

支持MVCC

支持外键

提供一致性非锁定读

有效利用CPU和内存

 

从MySQL5.1版本开始,允许存储引擎以动态方式加载,这样存储引擎的更新可以不受MySQL数据库版本的限制。

所以5.1中可以有静态编译的版本,也可以有动态加载的版本。

 

InnoDB体系架构

 

image

图2 InnoDB存储引擎体系架构

InnoDB存储引擎有多个内存块,可以认为这些内存块组成了一个大的内存池,负责:

维护所有进程/线程需要访问的多个内部数据结构

缓存磁盘上的数据

重做日志的缓冲(redo log)

 

后台线程的主要作用是负责刷新内存池中的数据,保证缓冲池内的数据是最近的数据;同时将脏数据刷回磁盘;保证数据库发生异常时InnoDB的恢复。

 

InnoDB是一个多线程模型,每个线程负责不同的任务。

1. Master Thread

2. IO Thread

3. Purge Thread

4. Page Cleaner Thread

 

内存

1. 缓冲池

2. LRU List、Free List和Flush List

3. 重做日志缓冲

4. 额外的内存池

 

CheckPoint技术

 

Master Thread工作方式

 

InnoDB的关键特性

插入缓冲(Insert Buffer)

两次写(Double Write)

自适应哈希索引(Adaptive Hash Index)

异步IO(Async IO)

刷新邻接页(Flush Neighbor Page)

 

启动、关闭与恢复

 

小结:感觉这章的内容还是挺重要的,对于理解InnoDB引擎或者底层实现

 

文件

MySQL和InnoDB存储引擎用到的文件有:

参数文件:

日志文件:

socket文件:

pid文件:

MySQL表结构文件:

存储引擎文件:

 

 

 

 

InnoDB存储引擎表的逻辑存储和实现,重点分析表的物理存储特征,即表中的数据是如何组织和存放的。

 

索引组织表

 

在InnoDB存储引擎中,表都是根据主键顺序存放的,这种存储方式的表称为索引组织表(index organized table)。

在InnoDB存储引擎表中,每张表都有个主键(Primary Key),如果创建表时没有显式地定义主键,则InnoDB存储引擎会按照如下方式选择或者创建主键:

首先判断表中是否有非空的唯一索引(Unique NOT NULL),如果有,则该列即为主键;

如果不符合上述条件,InnoDB存储引擎将选择建表时定义一个非空唯一索引主键。注意,主键的选择是根据的是定义索引的顺序,而不是建表时列的顺序。

 

 

InnoDB逻辑存储结构

 

在InnoDB中所有的数据都被逻辑地存放在一个空间中,称之为表空间(tablespace)。表空间又由段(segment)、区(extent)、页(page)组成。页在一些文档中也称之为块(block)。

 

image

图 InnoDB逻辑存储结构

表空间

 

 

 

 

 

 

 

InnoDB行记录格式

 

InnoDB存储引擎和大多数的数据库一样,记录是以行的形式存在的。即页中保存着表中一行行的数据。

在InnoDB 1.0.x版之前,InnoDB引擎提供了Compact和Redundant两种格式来存放行记录数据,这也是目前用得最多的,Redundant是为了兼容之前的版本而保留的。

数据库实例的作用之一就是读取页中存放的行记录。如果用户知道野种行记录的组织规则,也可以自行编写工具读取记录。

 

分表讲了一下Compact行记录格式和Redundant行记录格式。

 

 

行溢出数据

 

 

Compressed和Dynamic行记录格式

 

Char个行记录格式

 

InnoDB数据页结构

 

页是InnoDB引擎管理数据库的最小磁盘单位。页类型为B-tree Node的页存放的即是表中行的实际数据了。

 

 

Named File Formats机制

 

InnoDB存储引擎通过Named File Formats解决不同版本下页结构的兼容性问题。

 

 

约束

 

 

视图

 

分区表:水平分区和垂直分区

 

 

索引与算法

索引太多,程序的性能受到影响;

索引太少,查询的性能又会受到影响。So,必须找到一个平衡点。

 

image

 

对于数据的使用,从一开始就应该添加索引。

开发人员往往对于数据库的使用停留在应用层面,比如编写SQL语句、存储过程之类的,甚至不知道索引的存在。

DBA往往不够了解业务的数据流,而添加索引需要通过监控大量的SQL语句进而从中找到问题。这个步骤所需的时间肯定大于当初添加索引所需要的时间。索引也不是越多越好,索引越多导致磁盘占用很高。

 

这里对索引的内部机制了解,通过了解内部索引来了解哪里可以使用索引。

 

InnoDB存储引擎索引的概述

 

InnoDB支持的索引类型有:B+树索引、全文索引、哈希索引

 

InnoDB支持的哈希索引是自适应的,InnoDB存储引擎会根据表的使用情况自动为表生成哈希索引,不能人为干预是否在一张表中生成哈希索引。

image

自适应哈希索引

 

InvertedIndex

 

图 全文索引

 

image

 

 

B+树索引是传统意义上的索引, 也是目前关系型数据库中使用最多和最有效的索引。B不是binary的意思,而是balance的意思,可有效减少磁盘IO。

注意:B+树索引并不能够找到一个给定键值的具体行。B+树索引只能找到被查询数据行所在的页。然后通过将其读入内存,再在内存中进行查找。

image

 

 

image

 

image

 

 

数据结构与算法

 

关于B+ tree的

二分查找法(binary search):二分查找应用广泛,思想易于理解,但是直到1962年才有了第一个完全正确的二分查找法。

 

二叉查找树和平衡二叉树

 

B+树和二叉树、平衡二叉树一样都是经典的数据结构。

B+树由B树和索引顺序访问方法(ISAM)演化而来,但是现实中已经没有使用B树的情况了。

B+树的定义很复杂,总而言之:B+树是为磁盘或其他直接存取辅助设备设计的一种平衡查找树。

 

image

图 高度为2的B+树

 

B+树的插入操作

B+树的插入必须保证插入以后叶子节点中的记录依然排序,同时要考虑到插入到B+树中的三种情况,每个情况都有不同的插入算法。

image

图 B+树插入数据的三种不同情况

 

不管怎么插入数据,B+树总是会保持平衡,但是为了平衡性,对新插入的键值可能需要做大量的拆分页(split)操作。

因为B+树结构主要用于磁盘,页的拆分意味着磁盘操作,所以应当尽量减少页的拆分操作。

所以B+树提供了类似于平衡二叉树的旋转(Rotation)功能。

 

旋转发生在Leaf Page已满,但是左右兄弟节点没有满的情况下,B+树不会急于做拆分操作,而是将记录转移到所在页的兄弟节点上。

通常会先对左兄弟检查来做旋转操作。采用旋转操作使得B+树减少了一次页的拆分操作。

 

B+树的删除操作

B+树使用填充因子(fill factor)来控制树的删除变化,50%是填充因子的最小值。B+树的删除操作同样必须保证删除后叶子节点中的记录依然排序,删除也要考虑三种情况:

image

如果删除之后,Fill Factor小于50%,那么需要做合并操作。

 

B+树索引

 

B+树索引的本质就是B+树在数据库中的实现。但是B+树在数据库中的特点是高扇出性,什么鬼?就是叶节点多。

因此数据库中,B+树的高度一般都是在2~4层,也就是说查找某一键值最多需要2到4次IO。2~4次IO意味着查询时间只要0.02~0.04秒。

 

image

 

 

 

数据库中的B+树索引可以分为聚集索引(clustered index)和辅助索引(secondary index)。

 

聚集索引

 

image

图 聚集索引

 

Clustered-Indexes

图 聚集索引

 

 

clustereddiagram

图 聚集索引和非聚集索引的区别

 

InnoDB存储引擎表是索引组织表,即表中的数据按照主键顺序存放。

而聚集索引(clustered index)就是按照每张表的主键构造一颗B+树,同时叶子节点中存放的即为整张表的行记录数据,也将聚集索引的叶子节点称为数据页。

聚集索引的这个特性决定了索引组织表中数据也是索引的一部分。同B+树数据结构一样,每个数据页都通过一个双向链表来进行链接。

 

由于实际的数据页只能按照一颗B+树进行排序,因此每张表只能拥有一个聚集索引。在多数情况下,查询优化器倾向于采用聚集索引,

因为聚集索引能够在B+树索引的叶子节点上直接找到数据。

此外由于定义了数据的逻辑顺序,聚集索引能够特别快地访问针对范围值的查询。查询优化器能够快速地发现某一段范围的数据页需要扫描。

 

ZnJvbT1jbmJsb2dzJnVybD1IQmxTdUVUTWpsR1V2UTNib1JYWnVCM2NoOVNidk4yWHpkMmJzSm1iajlTYnZObUx6ZDJic0ptYmo1eWNsZFdZdGwyTHZvRGMwUkhh

图 聚集索引中的数据查找

 

ZnJvbT1jbmJsb2dzJnVybD1IQmxTdUFUTWpsR1V2UTNib1JYWnVCM2NoOVNidk4yWHpkMmJzSm1iajlTYnZObUx6ZDJic0ptYmo1eWNsZFdZdGwyTHZvRGMwUkhh

图 非聚集索引中的数据查找

注意,聚集索引如果按照特定的顺序存放物理数据,那么维护成本会很高。所以聚集索引的存储并不是物理上连续的,而是逻辑上连续的。

其中有两点:一时前面说到的页通过双向链表链接,页按照主键的顺序排序;

另一点是每个页中的记录也是通过双向链表进行维护的,物理存储上可以同样不按照主键存储。

 

 

聚集索引的另一个好处是,它对于主键的排序查找和范围查找的速度非常快,叶子节点的数据就是用户所要查找的数据。

 

虽然有通过order by进行排序,但是实际过程中并不会进行所谓的filesort,这是聚集索引的特点之一。

 

另一个是范围查找,即如果要查找主键某一范围内的数据,通过叶子节点的上层中间节点就可以得到页的范围,之后直接读取数据页即可。

 

辅助索引

 

辅助索引(secondary index),也成为非聚集索引,叶子节点并不包含记录的全部数据。叶子节点除了包含键值以外,每个叶子节点中还会包含了一个书签(bookmark)。

该书签用来告诉InnoDB存储引擎哪里可以找到与索引对应的行数据。

由于InnoDB存储引擎是索引组织表,因此InnoDB存储引擎的辅助索引的书签就是相应行数据的聚集索引键。

 

辅助索引的存在并不影响数据在聚集索引中的组织,因此每张表上可以有多个辅助索引。当通过辅助索引来寻找数据时,InnoDB存储引擎会遍历辅助索引并通过叶级别的指针

获得指向主键索引的主键,然后再通过主键索引来找到一个完整的行记录。

 

注意:辅助索引并不需要读取数据页,辅助索引中并不存放数据,全都是索引

 

5_4_architecture_of_non_clustered_index1

图 非聚集索引

 

 

Clustered-Indexes

图 非聚集索引

 

 

nci2

图 聚集索引与非聚集索引

上面这张图表现的还不错哦。

 

称为堆表的表类型是将行数据按照插入的顺序存放,堆表的特性决定了堆表上的索引都是非聚集索引,主键与非主键的区别只是是否唯一且非空(NOT NULL)。

此时书签是一个行标识(Row Identifier, RID),可以用如"文件号:页号:槽号"的格式来定位实际的数据行。

 

某些情况下堆表的确要比索引组织表更快,但也要考虑到数据是否需要更新,并且更新是否影响到物理地址的变更。

同时也不能忽视排序和查找。

非聚集索引的离散读,但是一般的数据库都通过实现预读(read ahead)技术来避免多次的离散读操作。

因此建立索引组织表还是堆表取决于具体应用。

 

unix-ch03032-21-638

图 预读

 

B+树索引的分裂

 

之前讲到的B+树的分裂是最为简单的一种情况,在数据库中的B+树分裂则有所不同。

因为之前的B+树分裂并没有涉及到并发,这是最难的一部分。

872539-20161107145043936-753882676

图 B+树的分裂

image

图 B+树的分裂

 

B+树的分裂也并不总是从中间开始,这样会导致页空间的浪费。

 

 

InnoDB存储引擎的Page Header中有以下几个部分用来保存插入的顺序信息:

PAGE_LAST_INSERT

PAGE_DIRECTION

PAGE_N_DIRECTION

通过这些信息,InnoDB存储引擎可以决定是向左还是向右分裂,同时决定将分裂点记为哪一个。

 

 

B+树索引的管理

 

索引的创建和删除可以通过两种方法,一种是ALTER TABLE,另一种是CREATE/DROP INDEX。

 

用户可以设置对整个列的数据进行索引,也可以只索引一个列的开头部分。

 

SHOW INDEX可以查看表中的索引信息。

 

Fast Index Creation

 

对于索引添加或者删除这类DDL操作,MySQL数据库的操作过程为:

首先创建一张新的临时表,表结构为通过命令ALTER TABLE新定义的结构

然后把原表中数据导入到临时表中

接着删除原表

最后把临时表重命名为原来的表名。

 

 

如果对一张很大的表进行索引的添加和删除操作,那么将耗费较长时间,更关键的是,若有大量事物需要访问正在被修改的表,这意味着数据库不可用。

 

InnoDB从 1.0.x开始支持一种称为FIC(快速索引创建)的索引创建方式。

 

对于辅助索引的创建,InnoDB存储引擎会对创建索引的表上加一个S锁。在创建的过程中不需要重建表。

 

删除辅助索引则更为简单了,InnoDB存储引擎只需要更新内部视图,并将辅助索引的空间标记为可用,同时删除MySQL数据库内部视图上对该表的索引定义即可。

 

 

 

Online Schema Change

 

The openarkkit toolkit oak-online-alter-table

 

Online DDL

 

 

Cardinality值

 

 

什么是Cardinality

并不是在所有的查询条件中出现的列都需要添加索引。

一般的经验是,在访问表中很少一部分时使用B+树索引才有意义。

对于性别字段、地区字段、类型字段,它们的取值的范围很小,称为低选择性。

 

 

相反,如果某个字段的取值范围很广,几乎没有重复,即属于高选择性,则此时使用B+树索引是非常合适的。

 

 

如果查看索引是否是高选择性的呢?

 

可以通过SHOW INDEX结果列中的Cardinality来观察。

Cardinality值非常关键,表示索引中不重复记录数量的预估值。

同时需要注意的是Cardinality是一个预估值,而不是准确值。

在实际应用中,Cardinality/n_rows_in_table应尽可能接近1,如果非常小,那么用户需要考虑是否还有必要建立这个索引。

 

 

B+树索引的使用

 

不同应用中使用B+树索引

联合索引

覆盖索引

 

优化器选择不使用索引的情况

 

 

索引提示

 

 

Multi-Range Read优化

 

 

ICP优化

 

 

哈希算法

 

InnoDB存储引擎中的哈希算法

 

自适应哈希算法

 

全文检索

 

 

 

 

开发多用户的系统时,最大的难点在于:一方面要最大程度利用数据库的并发访问,另外一方面还要确保每个用户能以一致的方式读取和修改数据。

为此就需要锁机制。

锁也是数据库区别于文件系统的一个关键特性。

 

这部分学习的是InnoDB如何对表中的数据进行锁定,以及以怎样的粒度锁定数据。

 

 

什么是锁?

 

 

锁机制用于管理共享资源的并发访问。InnoDB存储引擎会在行级别上对表数据上锁。

 

除了对数据表进行上锁之外,InnoDB也会在内部对其他的很多资源使用锁,从而允许对多种不同资源提供并发访问。

例如操作缓冲池中的LRU列表,删除、添加、移动LRU列表中的元素,为了保证一致性,必须有锁的介入,从而提供完整性和一致性。

 

对于MyISAM引擎,其锁是表锁设计,并发情况下的读没有问题,但是并发插入时的性能就要差一些。

 

 

lock与latch

 

在数据库中lock和latch都可以被称为锁,但是两者的含义截然不同。

 

latch一般称为闩锁,因其要求锁定的时间必须非常短,若持续的时间长,则应用性能会很差。在InnoDB存储引擎中,latch有可以分为mutex(互斥量)和rolock(读写锁)。其目的使用来保证并发线程操作临界资源的正确性,并且通常没有检测死锁的机制。

 

lock的对象是事务,用来锁定的是数据库中的对象,如表、页、行。并且一般lock的对象仅在事务commit或者rollback后进行释放(不同事务隔离级别释放的时间可能不同)。lock是有死锁机制的。

 

image

 

 

 

SHOW ENGINE INNODB MUTEX可以查看InnoDB存储引擎中的latch,输出结果的解释如下:

image

以上的信息都是比较底层的,一般仅供开发人员参考,但是用户还是可以使用这些参数进行调优。

 

 

InnoDB存储引擎中的锁

 

锁的类型

 

InnoDB存储引擎实现了如下两种标准的行级锁:

共享锁(S Lock),允许事务读一行数据。

排他锁(X Lock),允许事务删除或更新一行数据。

 

 

如果一个事务T1已经获取行r的共享锁,那么另外的事务T2可以立即获取行r的共享锁,因为读取并没有改变行r的数据,这种情况称为锁兼容(Lock Compatible)。

但若有其他的事务T3想获取行r的排他锁,则其必须等待事务T1、T2释放行r上的共享锁——称之为锁不兼容。

image

 

X锁与任何锁都不兼容,而S锁仅与S锁兼容。需要注意的是X和S都是行锁,兼容是指对同一记录(row)锁的兼容情况。

 

此外InnoDB存储引擎支持多粒度(granular)锁定,这种锁定允许事务在行级别上的锁和表级上的锁同时存在。

 

为了支持不同粒度上的锁,InnoDB存储引擎有一个额外的锁方式,称之为意向锁(Intention Lock)。意向锁是将锁定的对象分为多个层次,意向锁意味着事务希望在更细粒度(fine granularity)上进行加锁。

 

如果把上锁的对象看做一颗树,那么对最下层的对象上锁,也就是对最细粒度的对象上锁,那么首先需要对粗粒度的对象上锁。

 

image

如需对页上的记录r进行上X锁,那么分别需要对数据库A、表、页上意向锁IX,最后对记录r上X锁。

其中任何一部分导致等待,那么该操作需要等待粗粒度锁的完成。

 

举例就是,对记录r加X锁之前,已经有事务对表1进行了S表锁,那么表1上已经存在了S锁,之后事务需要对记录r在表上加IX,由于不兼容,所以对该事务需要等待表锁操作的完成。

 

InnoDB存储引擎支持的意向锁设计比价简单,其意向锁为表级别的锁。设计目的主要是为了在一个事务中揭示下一行将被请求的锁类型。

1. 意向共享锁(IS Lock),事务想要获得一张表中某几行的共享锁

2. 意向排他锁(IX Lock),事务想要获得一张表中某几行的排他锁

 

由于InnoDB存储引擎支持的是行级别的锁,因此意向锁其实不会阻塞除全表扫描以外的任何请求。

 

image

 

用户可以通过命令SHOW ENGINE INNODB STATUS命令来查看当前锁请求的信息。

 

可以看到SQL语句select * from  where a<4 lock in share mode在等待,

RECORD LOCKS space id 30 page no 3 n bits 72 index 'PRIMARY' of table 'test'.'t' trx id 48B89DB lock_mode X locks rec but not gap表示锁住的资源。

locks rec but not gap代表锁住的是一个索引,不是一个范围。

 

在InnoDB 1.0版本之前,用户只能通过命令SHOW FULL PROCESSLIST,SHOW ENGINE INNODB STATUS等来查看当前数据库中的锁请求,然后再判断事务锁的情况。

从InnoDB1.0开始,INFORMATION_SCHEMA架构下添加了表INNODB_TRX、INNODB_LOCKS、INNODB_LOCK_WAITS。

通过这三张表,用户可以更加单地监控当前事务并分析可能存在的问题。

 

image

image

 

image

 

 

一致性非锁定读(consistent nonlocking read)指的是InnoDB存储引擎通过多行版本控制(multi versioning)的方式来读取当前执行时间数据库中行的数据。

 

如果读取的行正在执行DELETE或者UPDATE操作,这时读取操作不会因此去等待行上锁的释放,相反的,InnoDB存储引擎会读取行的一个快照数据。

 

image

 

 

之所以成为非锁定读,是因为不需要等待访问的行上X锁的释放。

 

快照数据是指该行的之前版本的数据,该实现是通过undo段来完成。而undo用来在事务中回滚数据,因此快照数据本身是没有额外的开销。

此外快照数据的读取是不需要上锁的,因为没有事务需要对历史数据进行修改操作。

 

 

非锁定读机制极大提高了数据库的并发性。

在InnoDB存储引擎的默认设置下,这是默认的读取方式,即读取不会占用和等待表上的锁。

 

但是在不同事务隔离级别下,读取的方式不同,并不是在每个事务隔离级别下都是采用非锁定的一致性读。

此外即使使用非锁定的一致性读,但是对于快照数据的定义也各不相同。

 

快照数据就是当前行数据之前的历史版本,每行记录可能有多个版本。一行记录可能有不止一个快照数据,一般称这种技术为行多版本控制,由此带来的并发控制,

称为多版本并发控制(Multi Version Concurrency Control,MVCC)。

 

在事务隔离级别READ COMMITTED和REPEATABLE READ(InnoDB存储引擎默认的隔离级别)下,InnoDB存储引擎使用的是非锁定的一致性读。

然后对于快照数据的定义却不一样。

 

在READ COMMITTED事务隔离级别下,对于快照数据,非一致性读总是读取被锁定行的最新一份快照数据(fresh snapshot)。

而在REPEATEABLE READ事务隔离级别下,对于快照数据,非一致性读总是读取事务开始时的行数据版本。

 

 

BEGIN;

COMMIT;

 

image

 

 

非一致性锁定读

 

在默认配置下,即事务隔离级别为REPEATABLE READ模式下,InnoDB存储引擎的SELECT操作使用一致性非锁定读。

但是在某些情况下,用户需要显式地对数据库操作进行加锁以保证数据逻辑的一致性。

而这要求数据库支持加锁语句,即使对于SELECT的只读操作。

InnoDB存储引擎对于SELECT语句支持两种一致性的锁定读(locking read)操作:

SELECT ..... FOR UPDATE

SELECT ..... LOCK IN SHARE MODE

 

SELECT ...... FOR UPDATE对读取的行记录加一个X锁,其他事物不能对已锁定的行加上任何锁。

SELECT ...... LOCK IN SHARE MODE对读取的行记录加一个S锁,其他事务可以向被锁定的行加S锁,但是如果加X锁,则会被阻塞。

 

 

对于一致性非锁定读,即使读取的行已被执行了SELECT ..... FOR UPDATE,也是可以进行读取的。

此外,SELECT .... FOR UPDATE,SELECT ...... LOCK IN SHARE MODE必须在一个事务中,当事务提交了,锁也就被释放了。

 

因此在使用上面两句SELECT的时候,务必加上begin,start transaction或者set autocommit=0。

 

 

自增长和锁

 

外键和锁

 

 

 

锁的算法

 

行锁的三种算法:

Record Lock:单行记录的锁

Gap Lock:间隙锁,锁定一个范围,但不包含记录本身

Next-key Lock:Gap Lock + Record Lock,锁定一个范围,并锁定记录本身

 

解决Phantom Problem

 

 

锁问题

 

脏读

 

脏读就是指在不同的事务下,当前事务读到了另外事务未提交的数据。

 

不可重复读

 

丢失更新

 

 

阻塞

 

 

死锁

 

死锁的概念

 

 

死锁概率

 

 

死锁示例

 

锁升级

 

事务

 

数据库中事务的目的:事务会把数据库从一种一致状态转为另一种一致状态。

在数据库提交工作时,要么确保所有修改都已经保存了,要么所有修改都不保存。

 

ACID

原子性(atomicity)

一致性(consistency)

隔离性(isolation)

持久性(durability)

 

认识事务

 

事务有着严格的定义,必须同时满足四个特性,但是数据库厂商出于各种目的,并没有严格去满足事务的ACID标准。

对于InnoDB存储引擎而言,其默认的事务隔离级别READ REPEATABLE,完全遵循和满足事务的ACID特性。

 

分别介绍事务的四个特性

 

事务的分类

 

扁平事务(Flat Transaction)

带有保存点的扁平事务(Flat Transaction with Savepoints)

链事务(Chained Transactions)

嵌套事务(Nested Transactions)

分布式事务(Distributed Transactions)

 

 

 

事务的实现

 

 

事务控制语句

 

隐式提交的SQL语句

 

 

对事物操作的统计

 

每秒事务处理能力(Transaction Per Second)

 

事务的隔离级别

 

 

分布式事务

 

 

不好的事务习惯

 

 

长事务

 

 

备份与恢复

 

 

 

性能调优

转载于:https://www.cnblogs.com/tuhooo/p/7449918.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值