-
2021-10-13 21:19:14
MySQL 事务具有四大特性,分别是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
1、原子性(Atomicity)
原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。
2、一致性(Consistency)
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。举例来说,假设用户 A 和用户 B 两者的钱加起来一共是 1000,那么不管 A 和 B 之间如何转账,转几次账,事务结束后两个用户的钱相加还得是 1000,这就是事务的一致性。
3、隔离性(Isolation)
隔离性是当多个用户并发访问数据库时,比如同时操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。关于事务的隔离性数据库提供了多种隔离级别,详见 《MySQL 事务隔离级别和实现原理》。
4、持久性(Durability)
持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。例如我们在使用 JDBC 操作数据库时,在提交事务方法后,提示用户事务操作完成,当我们程序执行完成直到看到提示后,就可以认定事务已经正确提交,即使这时候数据库出现了问题,也必须要将我们的事务完全执行完成。否则的话就会造成我们虽然看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误,这是不允许的。
更多相关内容 -
Mysql 三大特性详解
2021-01-18 18:30:31Mysql Innodb后台线程工作方式首先Mysql进程模型是单进程多线程的。所以我们通过ps查找mysqld进程是只有一个。体系架构InnoDB存储引擎的架构如下图所以,是由多个内存块组成的内存池,同时又多个后台线程进行工作,...Mysql Innodb后台线程
工作方式
首先Mysql进程模型是单进程多线程的。所以我们通过ps查找mysqld进程是只有一个。
体系架构
InnoDB存储引擎的架构如下图所以,是由多个内存块组成的内存池,同时又多个后台线程进行工作,文件是存储磁盘上的数据。
后台线程
上面看到一共有四种后台线程,每种线程都在不停地做自己的工作,他们的分工如下:
Master Thread: 是最核心的线程,主要负责将缓冲池中的数据异步刷新的磁盘,保证数据的一致性,包括脏页的刷新、合并插入缓冲(INSERT BUFFER),UNDO页的回收等。下面几个线程其实是为了分担主线程的压力而在最新的版本中添加的。
IO Thread: InnoDB使用大量的异步IO来处理请求。IO Thread的主要工作就是负责IO请求的回调(call back)处理。异步IO可以分为4个,分别是:write, read, insert buffer 和 log IO thread。
Purge Thread: undo log是用来保证事务的,当一个事务正常提交后,这个undo log可能就不再使用了。purge thread就是用来清除这部分log已经分配的undo页的。
Page Cleaner Thread: 主要是把脏页的刷新从主线程中拿到单独的线程,减轻主线程的压力,减少用户查询线程的阻塞,提高整体性能。
Mysql Innodb内存结构
具体来看缓冲池中缓存的数据页类型有:
索引页: 缓存数据表索引
数据页: 缓存数据页,占缓冲池的绝大部分
undo页: undo页是保存事务,为回滚做准备的。
插入缓冲(Insert buffer): 上面提到的插入数据时要先插入到缓存池中。
自适应哈希索引(adaptive hash index): 除了B+ Tree索引外,在缓冲池还会维护一个哈希索引,以便在缓冲池中快速找到数据页。
InnoDB存储的锁信息(lock info):
数据字典(data dictionary):
内存中除了缓冲池外外还有:
重做日志缓冲redo log: 为了避免数据丢失的问题,当前数据库系统普遍采用了write ahead log策略,既当事务提交时先写重做日志,再修改写页。当由于发生宕机而导致数据丢失时,可以通过重做日志进行恢复。InnoDB先将重做日志放到这个缓冲区,然后按照一定的频率更新到重做日志文件中。重做日志一般在下列情况下会刷新内容到文件:
1.Master Thread每一秒将重做日志缓冲刷新到重做日志文件
2.每个事务提交时会将重做日志缓冲刷新到重做日志文件
3.当重做日志缓冲池剩余空间小于1/2时,重做日志缓冲刷新到重做日志文件
额外内存池: InnoDB存储引擎中,对内存的管理师通过一种称为内存堆的方式进行的,在对一些数据结构本身的内存进行分配时,需要从额外的内存池中进行申请,当该区域的内存不够时,会从缓冲池中进行申请。
缓冲池是一个很大的内存区域,InnoDB是如何对这些内存进行管理的呢。答案就使用LRU list。
LRU(Latest Recent Used, 最近最少使用)算法默认的是最近使用的放到表头,最早使用的放到表尾,依次排列。当有LRU填满时有新的进来就把最早的淘汰掉。InnoDB则是在这个基础上进行了修改:
最近使用的不放到表头,而是根据配置放到一定比例处,这个地方叫做midpoint, midpoint之前的成为new列表,之后的成为old列表。淘汰的同样是表尾的页。
为了保证new列表的不经常使用时能够淘汰,设置了一个超时时间:innodb_old_blocks_time,当数据在midpoint(我理解应该是在old列表中,不然这个点的页就一个,变化也比较频繁)的时间超过找个时间时就会被提升到表头,new列表的表尾页则被置换到old列表中。
这么做的原因主要是因为常见的索引或数据的扫描操作会连续读取大量的页,甚至是全表扫描。如果采用原来的LRU算法就会更新全部的缓冲池,其他查询需要的热点数据就会被冲走,导致更多的磁盘读取操作,降低数据库的性能。
LRU是用来管理已经读取的页,当数据库启动时LRU是空列表,既只有表头,没有内容。这时页都放在Free List中。当需要有数据读写时要进行需要获取分页,这时要从Free List中删除分页,然后添加到LRU list中。到一定时间Free List中的分页就会被分配完毕,这时候就正常使用上面的LRU策略。
LRU列表中的页被修改后,称该页为脏页(dirty page),既缓冲池中的数据和磁盘上的数据产生了不一致,这时脏页会被加入到一个Flush 列表中(注意,同时存在两个列表中)。然后根据刷新的机制定时的刷新到磁盘中。
三大特性之一插入缓冲
1.1聚簇索引与非聚簇索引的区别
聚集索引的叶子节点存储的是数据,而且是按照物理顺序存储的;非聚集索引叶子节点是地址(也就是聚集索引键地址),是按照逻辑顺序存储的(以上言论是从网上了解到的,但是本书P194特别指出,聚集索引也不是按照物理地址连续的,而是逻辑上连续的)。
1.2高并发后的insert会发生什么?
mysql> create table t ( id int auto_increment,
name varchar(30),primary key (id),key(name));
Query OK, 0 rows affected (0.21 sec)
我们知道,主键是行唯一的标识符,在应用程序中行记录的插入顺序是按照主键递增的顺序进行插入的。因此,插入聚集索引一般是顺序的,不需要磁盘的随机读取,速度会很快,但是我们看到上一个表还有一个叫做name的索引字段,这样的情况下产生了一个非聚集的并且不是唯一的索引。在进行插入操作时,数据页的存放还是按主键id的执行顺序存放,但是对于非聚集索引,叶子节点的插入不再是顺序的了。这时就需要离散地访问非聚集索引页,插入性能在这里变低了。然而这并不是这个name字段上索引的错误,是因为B+树的特性决定了非聚集索引插入的离散性。
1.3插入缓冲的实现
在innodb的1.0x版本开始,引入了change buffer,可以把它看成insert buffer的升级版,innodb可以对DML操作-INSERT/DELETE/UPDATE都进行缓冲。
1.将一个辅助索引插入到页(space,offset)
2.检查这个页是否在缓冲池中
在:直接插入
不在:继续
3.缓存进入insert buffer
4.构造一个search key
5.查询insert buffer树
6.生成逻辑记录并插入树中
1.3.1insert buffer内部实现原理
在mysql4.1版本之后,insert buffer是通过一全局唯一的一个B+树进行管理所有表的辅助索引。而这颗树存放在共享表空间中,格式为ibdata1,所以如果试图通过独立表空间idb文件恢复表中数据的时候,往往会导致CHECK TABLE失败,这是因为表的辅助索引中的数据可能还在INSERT BUFFER中,也就是共享表空间中,所以通过ibd文件进行恢复后,还需要进行REPAIR TABLE 操作来重建表上所有的辅助索引。
insert buffer的b+树的非叶子节点存放的是查询的search key(键值),其构造如图:
space为表空间id
marker用来兼容老版本
offset表示页所在偏移量
叶子节点会比非叶子节点多俩数据,一个是metadata,一个是secondary index record。
metadata 记录的每一列的类型,长度
secondary index record 记录的具体值
为了保证每个辅助索引页Merge Insert Buffer的B+树必须成功,还需要有一个特殊的页用来标记每个辅助索引页(space,page_no)的可用空间。这个页的类型为Insert Buffer Bitmap。它会标记16385个辅助索引页,每个辅助索引页会在其中占用4bit的位置来记录信息,具体信息如下:
Merge Insert Buffer的操作可能发生在以下几种情况下:
辅助索引页被读取到缓冲池时;
Insert Buffer Bitmap页追踪到该辅助索引页已无可用空间时;
Master Thread。
第一种情况为当辅助索引页被读取到缓冲池中时,例如这在执行正常的SELECT查询操作,这时需要检查Insert Buffer Bitmap页,然后确认该辅助索引页是否有记录存放于Insert Buffer B+树中。若有,则将Insert Buffer B+树中该页的记录插入到该辅助索引页中。可以看到对该页多次的记录操作通过一次操作合并到了原有的辅助索引页中,因此性能会有大幅提高。
Insert Buffer Bitmap页用来追踪每个辅助索引页的可用空间,并至少有1/32页的空间。若插入辅助索引记录时检测到插入记录后可用空间会小于1/32页,则会强制进行一个合并操作,即强制读取辅助索引页,将Insert Buffer B+树中该页的记录及待插入的记录插入到辅助索引页中。这就是上述所说的第二种情况。
还有一种情况,之前在分析Master Thread时曾讲到,在Master Thread线程中每秒或每10秒会进行一次Merge Insert Buffer的操作,不同之处在于每次进行merge操作的页的数量不同。
1.4缓冲的限制条件
插入缓冲的启用需要满足一下两个条件:
1)索引是辅助索引(secondary index)
2)索引不适合唯一的
原因是因为插入缓冲本身就是为了解决二级索引离散插入的问题,所以建立一个缓冲区将部分离散的索引数据合并,使用一次大的IO操作统一刷到磁盘,如果索引是唯一的,那这么做将失去意义,而且每次还需要去询问数据页是否已经存在,还会增加额外的IO操作。
1.5插入缓冲性能影响
任何一项技术在带来好处的同时,必然也带来坏处。插入缓冲主要带来如下两个坏处:
1)可能导致数据库宕机后实例恢复时间变长。如果应用程序执行大量的插入和更新操作,且涉及非唯一的聚集索引,一旦出现宕机,这时就有大量内存中的插入缓冲区数据没有合并至索引页中,导致实例恢复时间会很长。
2)在写密集的情况下,插入缓冲会占用过多的缓冲池内存,默认情况下最大可以占用1/2,这在实际应用中会带来一定的问题。
1.6观察
show engine innodb status\g;
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 2 merges
merged operations:
insert 0, delete mark 0, delete 0
discarded operations:
insert 0, delete mark 0, delete 0
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 1 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 1 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
0.00 hash searches/s, 0.00 non-hash searches/s
从上面可以看到其中有一部分叫做INSERT BUFFER AND ADAPTIVE HASH INDEX,其中的seg size指的就是当前insert buffer的大小,具体计算方式为seg_size*16KB =32KB,free list len表示空闲列表的长度,size表示已经合并记录页的数量。
三大特性之二double write
2.1、基本概念
2.1.1页断裂(partial write)
所谓页断裂是数据库宕机时(OS重启,或主机掉电重启),数据库页面只有部分写入磁盘,导致页面出现不一致的情况。那么为什么会不一样呢?因为数据库,OS和磁盘读写的基本单位是块,也可以称之为(page size)block size。我们知道数据库的块一般为8K,16K;而OS的块则一般为4K;IO块则更小,linux内核要求IO block
size<=OS block size。磁盘IO除了IO block size,还有一个概念是扇区(IO sector),扇区是磁盘物理操作的基本单位,而IO 块是磁盘操作的逻辑单位,一个IO块对应一个或多个扇区,扇区大小一般为512个字节。所以各个块大小的关系可以梳理如下:
DB block > OS block >= IO block > 磁盘 sector,而且他们之间保持了整数倍的关系。所以说当数据库突然宕机,就会造成部分DB block的数据实际上并未写入到磁盘的sector中,出现了页断裂的情况,进而导致数据不一致的现象。
2.1.2数据库日志的三种格式
数据库系统实现日志主要有三种格式,逻辑日志(logical logging),物理日志(physical logging),物理逻辑日志(physiological logging),逻辑日志,记录一个个逻辑操作,不涉及物理存储位置信息,比如mysql的binlog;物理日志,则是记录一个个具体物理位置的操作,比如在2号表空间,1号文件,48页的233这个offset地方写入了8个字节的数据,通过(group_id,file_id,page_no,offset)4元组,就能唯一确定数据存储在磁盘的物理位置;物理逻辑日志是物理日志和逻辑日志的混合,如果一个数据库操作(DDL,DML,DCL)产生的日志跨越了多个页面,那么会产生多个物理页面的日志,但对于每个物理页面日志,里面记录则是逻辑信息。这里我举一个简单的INSERT操作来说明几种日志形式。
比如innodb表T(c1,c2, key key_c1(c1)),插入记录row1(1,’abc’)
逻辑日志:
逻辑物理日志:因为表T含有索引key_c1, 一次插入操作至少涉及两次B树操作,二次B树必然涉及至少两个物理页面,因此至少有两条日志
物理理日志:由于一次INSERT操作,物理上来说要修改页头信息(如,页内的记录数要加1),要修改相邻记录里的链表指针,要修改Slot属性等,因此对应逻辑物理日志的每一条日志,都会有N条物理日志产生。
< group_id,file_id,page_no,offset1, value1>
< group_id,file_id,page_no,offset2, value2>
……
< group_id,file_id,page_no,offsetN, valueN>因此对于上述一个INSERT操作,会产生一条逻辑日志,二条逻辑物理日志,2*N条物理日志。从上面简单的分析可以看出,逻辑日志的日志量最小,而物理日志的日志量最大;物理日志是纯物理的;而逻辑物理日志则页间物理,页内逻辑,所谓physical-to-a-page, logical-within-a-page。
2.2 数据一致性
2.2.1页断裂和数据一致性
前面我们分析了异常重启导致页断裂的原因,而页断裂就意味着数据库页面不完整,那么数据库页面不完整就意味着数据库不一致。我们知道,数据库异常重启时,自身有异常恢复机制,主流数据库基本原理类似:第一阶段重做redo日志,恢复数据页和undo页到异常crash时的状态;第二阶段,根据undo页的内容,回滚没有提交事务的修改。通过两个阶段保证了数据库的一致性。对于mysql而言,在第一阶段,若出现页断裂问题,则无法通过重做redo日志恢复,进而导致恢复中断,数据库不一致。这里大家可能会有疑问,数据库的redo不是记录了所有的变更,并且是物理的吗?理论上来说,无论页面是否断裂,从上一个检查点对应的redo位置开始,一直重做redo,页面自然能恢复到正常状态。对吗?
2.2.2redo格式与数据一致性
回到“发生页断裂后,是否会影响数据库一致性”的问题,发生页断裂后,对于利用纯物理日志实现redo的数据库不受影响,因为每一条redo日志完全不依赖物理页的状态,并且是幂等的(执行一次与N次,结果是一样的),而逻辑物理日志则不行,比如修改页头信息,页内记录数加1,slot信息修改等都依赖于页面处于一个一致状态,否则就无法正确重做redo。而mysql正是采用这种日志类型,另外要说明一点,redo日志的页大小一般设计为512个字节,因此redo日志页本身不会发生页断裂。所以发生页面断裂时,异常恢复就会出现问题,需要借助于double write技术来辅助处理。
2.3 doubleWrite的实现
在InnoDB将BP中的Dirty Page刷(flush)到磁盘上时,首先会将(memcpy函数)Page刷到InnoDB tablespace的一个区域中,我们称该区域为Double write Buffer(大小为2MB,每次写入1MB,128个页,每个页16k,其中120个页为后台线程的批量刷Dirty Page,还有8个也是为了前台起的sigle Page Flash线程,用户可以主动请求,并且能迅速的提供空余的空间)。在向Double write Buffer写入成功后,第二步、再将数据分别刷到一个共享空间和真正应该存在的位置。具体的流程如下图所示:
2.4doubleWrite的保护机制
下面来看下在不同的写入阶段,操作系统crash后,double write带来的保护机制:
阶段一:copy过程中,操作系统crash,重启之后,脏页未刷到磁盘,但更早的数据并没有发生损坏,重新写入即可阶段二:write到共享表空间过程中,操作系统crash,重启之后,脏页未刷到磁盘,但更早的数据并没有发生损坏,重新写入即可阶段三:write到独立表空间过程中,操作系统crash,重启之后,发现:(1)数据文件内的页损坏:头尾checksum值不匹配(即出现了partial page write的问题)。从共享表空间中的doublewrite segment内恢复该页的一个副本到数据文件,再应用redo log;(2)若页自身的checksum匹配,但与doublewrite segment中对应页的checksum不匹配,则统一可以通过apply redo log来恢复。)阶段X:recover过程中,操作系统crash,重启之后,innodb面对的情况同阶段三一样(数据文件损坏,但共享表空间内有副本),再次应用redo log即可。
2.5doubleWrite对性能的影响
系统需要将数据写两份,一般认为,Double Write是会降低系统性能的。peter猜测可能会有5-10%的性能损失,但是因为实现了数据的一致,是值得的。Mark Callaghan认为这应该是存储层面应该解决的问题,放在数据库层面无疑是牺牲了很多性能的。事实上,Double Write对性能影响并没有你想象(写两遍性能应该降低了50%吧?)的那么大。在BP中一次性往往会有很多的Dirty Page同时被flush,Double Write则把这些写操作,由随机写转化为了顺序写。而在Double Write的第二个阶段,因为Double Write Buffer中积累了很多Dirty Page,所以向真正的数据文件中写数据的时候,可能有很多写操作可以合并,这样有可能会降低Fsync的调用次数。基于上面的原因,Double Write并没有想象的那么糟。最后发现打开和关闭Double Write对效率的影响并不大。
三大特性之三自适应哈希索引
哈希索引只有Memory, NDB两种引擎支持,Memory引擎默认支持哈希索引,如果多个hash值相同,出现哈希碰撞,那么索引以链表方式存储。但是,Memory引擎表只对能够适合机器的内存切实有限的数据集。要使InnoDB或MyISAM支持哈希索引,可以通过伪哈希索引来实现,但是innodb还实现了一种叫做自适应哈希索引来达到目的。
InnoDB存储引擎会监控对表上各索引页的查询。如果观察到建立哈希索引可以带来速度提升,则建立哈希索引,称之为自适应哈希索引(Adaptive Hash Index, AHI)。AHI是通过缓冲池的B+树页构造而来,因此建立的速度很快,而且不需要对整张表构建哈希索引。InnoDB存储引擎会自动根据访问的频率和模式来自动地为某些热点页建立哈希索引。
3.1、状态监控
mysql> show engine innodb status\G
……
Hash table size 34673, node heap has 0 buffer(s)
0.00 hash searches/s, 0.00 non-hash searches/s
1、34673:字节为单位,占用内存空间总量
2、通过hash searches、non-hash searches计算自适应hash索引带来的收益以及付出,确定是否开启自适应hash索引
3.2、限制
1、只能用于等值比较,例如=, <=>,in
2、无法用于排序
3、有冲突可能
4、MySQL自动管理,人为无法干预。
3、自适应哈希索引的控制
由于innodb不支持hash索引,但是在某些情况下hash索引的效率很高,于是出现了adaptive hash index功能,但是通过上面的状态监控,可以计算其收益以及付出,控制该功能开启与否。
-
数据库四大特性
2021-03-03 23:50:02数据库系统必须维护事务的以下特性(简称ACID):原子性(Atomicity)一致性(Consistency)隔离性(Isolation)持久性(Durability)⑴ 原子性(Atomicity)原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此...数据库系统必须维护事务的以下特性(简称ACID):
原子性(Atomicity)
一致性(Consistency)
隔离性(Isolation)
持久性(Durability)
⑴ 原子性(Atomicity)
原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。
⑵ 一致性(Consistency)
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。
拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。
⑶ 隔离性(Isolation)
隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。
关于事务的隔离性数据库提供了多种隔离级别。
⑷ 持久性(Durability)
持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
数据库事务的四大特性:
事务(Transaction)是并发控制的基本单位。所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。例如,银行转帐工作:从一个帐号扣款并使另一个帐号增款,这两个操作要么都执行,要么都不执行。
1、数据库事务必须具备ACID特性,ACID是Atomic(原子性)、Consistency(一致性)、Isolation(隔离性)和Durability(持久性)的英文缩写。
1)原子性(Atomicity)
一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
2)一致性(Consistency)
事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。如果事务成功地完成,那么系统中所有变化将正确地应用,系统处于有效状态。如果在事务中出现错误,那么系统中的所有变化将自动地回滚,系统返回到原始状态。
3)隔离性(Isolation)
指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。
4)持久性(Durability)
指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。
2、事务的(ACID)特性是由关系数据库管理系统(RDBMS,数据库系统)来实现的。数据库管理系统采用日志来保证事务的原子性、一致性和持久性。日志记录了事务对数据库所做的更新,如果某个事务在执行过程中发生错误,就可以根据日志,撤销事务对数据库已做的更新,使数据库退回到执行事务前的初始状态。
数据库管理系统采用锁机制来实现事务的隔离性。当多个事务同时更新数据库中相同的数据时,只允许持有锁的事务能更新该数据,其他事务必须等待,直到前一个事务释放了锁,其他事务才有机会更新该数据。
3、在关系型数据库中,事务的隔离性分为四个隔离级别,在解读这四个级别前先介绍几个关于读数据的概念。
1)脏读(Dirty Reads):所谓脏读就是对脏数据(Drity Data)的读取,而脏数据所指的就是未提交的数据。也就是说,一个事务正在对一条记录做修改,在这个事务完成并提交之前,这条数据是处于待定状态的(可能提交也可能回滚),这时,第二个事务来读取这条没有提交的数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被称为脏读。
2)不可重复读(Non-Repeatable Reads):一个事务先后读取同一条记录,但两次读取的数据不同,我们称之为不可重复读。也就是说,这个事务在两次读取之间该数据被其它事务所修改。
3)幻读(Phantom Reads):一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为幻读。
-
MySQL数据库三种常用存储引擎特性对比
2020-09-10 05:06:26MySQL中的数据用各种不同的技术存储在文件(或内存)中,这些技术中的每一种技术都使用不同的存储机制,索引技巧,锁定水平并且最终提供广泛的不同功能和能力。在MySQL中将这些不同的技术及配套的相关功能称为存储... -
MySQL8新特性:自增主键的持久化详解
2020-09-09 09:01:27MySQL8.0 GA版本发布了,展现了众多新特性,下面这篇文章主要给大家介绍了关于MySQL8新特性:自增主键的持久化的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧 -
MySQL 5.7新特性介绍
2020-09-10 02:07:17主要为大家详细介绍了MySQL 5.7新特性,了解一下MySQL 5.7的部分新功能,需要的朋友可以参考下 -
必须了解的mysql三大日志
2020-09-02 22:28:26mysql日志主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。作为开发,我们重点需要关注的是二进制日志(binlog)和事务日志(包括redo log和undo log),本文接下来会详细介绍这三种日志。 binlog...日志是
mysql
数据库的重要组成部分,记录着数据库运行期间各种状态信息。mysql
日志主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。作为开发,我们重点需要关注的是二进制日志(binlog
)和事务日志(包括redo log
和undo log
),本文接下来会详细介绍这三种日志。binlog
binlog
用于记录数据库执行的写入性操作(不包括查询)信息,以二进制的形式保存在磁盘中。binlog
是mysql
的逻辑日志,并且由Server
层进行记录,使用任何存储引擎的mysql
数据库都会记录binlog
日志。逻辑日志:可以简单理解为记录的就是sql语句。
物理日志:因为
mysql
数据最终是保存在数据页中的,物理日志记录的就是数据页变更。binlog
是通过追加的方式进行写入的,可以通过max_binlog_size
参数设置每个binlog
文件的大小,当文件大小达到给定值之后,会生成新的文件来保存日志。binlog使用场景
在实际应用中,
binlog
的主要使用场景有两个,分别是主从复制和数据恢复。1、 主从复制:在
Master
端开启binlog
,然后将binlog
发送到各个Slave
端,Slave
端重放binlog
从而达到主从数据一致。 2、 数据恢复:通过使用mysqlbinlog
工具来恢复数据。binlog刷盘时机
对于
InnoDB
存储引擎而言,只有在事务提交时才会记录biglog
,此时记录还在内存中,那么biglog
是什么时候刷到磁盘中的呢?mysql
通过sync_binlog
参数控制biglog
的刷盘时机,取值范围是0-N
:- 0:不去强制要求,由系统自行判断何时写入磁盘;
- 1:每次
commit
的时候都要将binlog
写入磁盘; - N:每N个事务,才会将
binlog
写入磁盘。
从上面可以看出,
sync_binlog
最安全的是设置是1
,这也是MySQL 5.7.7
之后版本的默认值。但是设置一个大一些的值可以提升数据库性能,因此实际情况下也可以将值适当调大,牺牲一定的一致性来获取更好的性能。binlog日志格式
binlog
日志有三种格式,分别为STATMENT
、ROW
和MIXED
。在
MySQL 5.7.7
之前,默认的格式是STATEMENT
,MySQL 5.7.7
之后,默认值是ROW
。日志格式通过binlog-format
指定。STATMENT
基于SQL
语句的复制(statement-based replication, SBR
),每一条会修改数据的sql语句会记录到binlog
中。 优点:不需要记录每一行的变化,减少了binlog
日志量,节约了IO
, 从而提高了性能; 缺点:在某些情况下会导致主从数据不一致,比如执行sysdate()
、slepp()
等。ROW
基于行的复制(row-based replication, RBR
),不记录每条sql语句的上下文信息,仅需记录哪条数据被修改了。 优点:不会出现某些特定情况下的存储过程、或function、或trigger的调用和触发无法被正确复制的问题; 缺点:会产生大量的日志,尤其是alter table
的时候会让日志暴涨MIXED
基于STATMENT
和ROW
两种模式的混合复制(mixed-based replication, MBR
),一般的复制使用STATEMENT
模式保存binlog
,对于STATEMENT
模式无法复制的操作使用ROW
模式保存binlog
redo log
为什么需要redo log
我们都知道,事务的四大特性里面有一个是持久性,具体来说就是只要事务提交成功,那么对数据库做的修改就被永久保存下来了,不可能因为任何原因再回到原来的状态。那么
mysql
是如何保证一致性的呢?最简单的做法是在每次事务提交的时候,将该事务涉及修改的数据页全部刷新到磁盘中。但是这么做会有严重的性能问题,主要体现在两个方面:1、 因为
Innodb
是以页
为单位进行磁盘交互的,而一个事务很可能只修改一个数据页里面的几个字节,这个时候将完整的数据页刷到磁盘的话,太浪费资源了! 2、 一个事务可能涉及修改多个数据页,并且这些数据页在物理上并不连续,使用随机IO写入性能太差!因此
mysql
设计了redo log
,具体来说就是只记录事务对数据页做了哪些修改,这样就能完美地解决性能问题了(相对而言文件更小并且是顺序IO)。redo log基本概念
redo log
包括两部分:一个是内存中的日志缓冲(redo log buffer
),另一个是磁盘上的日志文件(redo log file
)。mysql
每执行一条DML
语句,先将记录写入redo log buffer
,后续某个时间点再一次性将多个操作记录写到redo log file
。这种先写日志,再写磁盘的技术就是MySQL
里经常说到的WAL(Write-Ahead Logging)
技术。在计算机操作系统中,用户空间(
user space
)下的缓冲区数据一般情况下是无法直接写入磁盘的,中间必须经过操作系统内核空间(kernel space
)缓冲区(OS Buffer
)。因此,redo log buffer
写入redo log file
实际上是先写入OS Buffer
,然后再通过系统调用fsync()
将其刷到redo log file
中,过程如下:mysql
支持三种将redo log buffer
写入redo log file
的时机,可以通过innodb_flush_log_at_trx_commit
参数配置,各参数值含义如下:redo log记录形式
前面说过,
redo log
实际上记录数据页的变更,而这种变更记录是没必要全部保存,因此redo log
实现上采用了大小固定,循环写入的方式,当写到结尾时,会回到开头循环写日志。如下图:同时我们很容易得知,在innodb中,既有
redo log
需要刷盘,还有数据页
也需要刷盘,redo log
存在的意义主要就是降低对数据页
刷盘的要求。在上图中,write pos
表示redo log
当前记录的LSN
(逻辑序列号)位置,check point
表示数据页更改记录刷盘后对应redo log
所处的LSN
(逻辑序列号)位置。write pos
到check point
之间的部分是redo log
空着的部分,用于记录新的记录;check point
到write pos
之间是redo log
待落盘的数据页更改记录。当write pos
追上check point
时,会先推动check point
向前移动,空出位置再记录新的日志。启动
innodb
的时候,不管上次是正常关闭还是异常关闭,总是会进行恢复操作。因为redo log
记录的是数据页的物理变化,因此恢复的时候速度比逻辑日志(如binlog
)要快很多。 重启innodb
时,首先会检查磁盘中数据页的LSN
,如果数据页的LSN
小于日志中的LSN
,则会从checkpoint
开始恢复。 还有一种情况,在宕机前正处于checkpoint
的刷盘过程,且数据页的刷盘进度超过了日志页的刷盘进度,此时会出现数据页中记录的LSN
大于日志中的LSN
,这时超出日志进度的部分将不会重做,因为这本身就表示已经做过的事情,无需再重做。redo log与binlog区别
由
binlog
和redo log
的区别可知:binlog
日志只用于归档,只依靠binlog
是没有crash-safe
能力的。但只有redo log
也不行,因为redo log
是InnoDB
特有的,且日志上的记录落盘后会被覆盖掉。因此需要binlog
和redo log
二者同时记录,才能保证当数据库发生宕机重启时,数据不会丢失。undo log
数据库事务四大特性中有一个是原子性,具体来说就是 原子性是指对数据库的一系列操作,要么全部成功,要么全部失败,不可能出现部分成功的情况。实际上,原子性底层就是通过
undo log
实现的。undo log
主要记录了数据的逻辑变化,比如一条INSERT
语句,对应一条DELETE
的undo log
,对于每个UPDATE
语句,对应一条相反的UPDATE
的undo log
,这样在发生错误时,就能回滚到事务之前的数据状态。同时,undo log
也是MVCC
(多版本并发控制)实现的关键,这部分内容在[面试中的老大难-mysql事务和锁,一次性讲清楚!][-mysql]中有介绍,不再赘述。 -
高性能mysql 第三版 高清 pdf
2019-01-13 22:53:55第3 版更新了大量的内容,不但涵盖了最新MySQL 5.5版本的新特性,也讲述了关于固态盘、高可扩展性设计和云计算环境下的数据库相关的新内容,原有的基准测试和性能优化部分也做了大量的扩展和补充。全书共分为16 章和... -
官方发布的mysql8.0新特性
2018-07-12 12:59:51官方发布的mysql8.0新特性PPT,官方发布的mysql8.0新特性PPT,官方发布的mysql8.0新特性PPT -
MySQL 8.0 新特性之哈希连接(Hash Join)
2020-09-09 00:27:13MySQL 开发组于 2019 年 10 月 14 日 正式发布了 MySQL 8.0.18 GA 版本,带来了一些新特性和增强功能。这篇文章主要介绍了MySQL 8.0 新特性之哈希连接(Hash Join),需要的朋友可以参考下 -
高性能MYSQL第三版
2018-09-29 10:54:45第3版更新了大量的内容,不但涵盖了最新MySQL5.5版本的新特性,也讲述了关于固态盘、高可扩展性设计和云计算环境下的数据库相关的新内容,原有的基准测试和性能优化部分也做了大量的扩展和补充。全书共分为16章和6个... -
MySql Innodb 引擎特性详解
2017-02-28 14:20:26MySql Innodb 引擎特性详解 -
高性能MySQL(第三版).pdf
2018-03-14 18:49:05《高性能MySQL(影印版)(第3版)(中文版)》学习MySQL5.5版提供的新特性,包括存储过程、数据库分区、触发器和视图,实现在复制、高可用性和集群上的改进,实现MySQL在云环境中运行的高性能,优化高级查询特性,如全文... -
超详细的MySQL三万字总结
2021-08-22 21:27:51文章目录MySQL基础数据库的介绍数据库概述数据的存储方式数据库的概念常见数据库排行榜数据库的安装与卸载数据库的安装数据库的卸载数据库服务的启动与登录Windows 服务方式启动DOS 命令方式启动控制台连接数据库... -
浅谈mysql8.0新特性的坑和解决办法(小结)
2020-09-09 07:45:21主要介绍了浅谈mysql8.0新特性的坑和解决办法(小结),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 -
MySQL5.7版本新特性介绍视频教程Mysql特性及版本介绍视频教程
2019-07-23 02:32:16课程目录MySQL5.7版本新特性1-1初始化方式变更.mp41-2初始化方式变更实战演练.mp41-3旧版本支持为表增加计算列演练.mp41-4MySQL5.7支持为表增加计算列实际演练.mp41-5引入JSON列类型及相关函数.mp42-1支持多源复制.... -
Mysql - InnoDB三大特性之双写缓冲区(Double Write Buffer)
2021-03-25 01:22:05双写缓冲区是InnoDB的大特性之一,还有两个是 Buffer Pool简称BP、自适应Hash索引。doublewrite缓冲区是一个存储区,在该存储区中,在InnoDB将页面写入InnoDB数据文件中的适当位置之前,先从缓冲池中刷新页面。如果... -
MySQL8.0.11版本的新增特性介绍
2020-09-09 10:01:38主要介绍了MySQL8.0.11版本的新增特性介绍,非常不错,具有参考借鉴价值,需要的朋友可以参考下 -
[MySQL] InnoDB三大特性之 - 自适应哈希索引
2015-04-08 16:07:51它查找的时间复杂度为常量,InnoDB采用自适用哈希索引技术,它会实时监控表上索引的使用情况,如果认为建立哈希索引可以提高查询效率,则自动在内存中的“自适应哈希索引缓冲区”(详见《MySQL - 浅谈InnoDB体系... -
高性能MySQL-中文第三版.pdf
2018-07-25 14:50:17第3版更新了大量的内容,不但涵盖了最新MySQL5.5版本的新特性,也讲述了关于固态盘、高可扩展性设计和云计算环境下的数据库相关的新内容,原有的基准测试和性能优化部分也做了大量的扩展和补充。全书共分为16章和6个... -
高性能MySQL(第三版)_带目录
2018-09-11 23:25:09第3 版更新了大量的内容,不但涵盖了MySQL5.5版本的新特性,也讲述了关于固态盘、高可扩展性设计和云计算环境下的数据库相关的新内容,原有的基准测试和性能优化部分也做了大量的扩展和补充。全书共分为16章和6 个... -
利用mysql事务特性实现并发安全的自增ID示例
2020-09-10 17:23:43项目中经常会用到自增id,比如uid,下面为大家介绍下利用mysql事务特性实现并发安全的自增ID,感兴趣的朋友可以参考下 -
MySQL常见的三种锁以及特性
2020-05-07 23:39:02打卡(2020-05-07) 锁问题的由来 锁是计算机协调多个线程并发访问某一资源的机制...常见的三种锁,锁的特性如下 表级锁:开销小,加锁快;不会出现死锁,锁定粒度大,发生锁冲突的概率最高,并发度最低。 页面锁:开... -
MySQL高级特性
2017-06-14 21:44:38MySQL高级特性,尚硅谷的教学笔记 -
MYSQL INNODB 三大特性之双写
2018-07-30 16:30:12本文属于《MYSQL运维内参》第九章读书笔记,因为INNODB的三大特性:插入缓存,两次写,自适应hash,还是觉得作者先介绍插入缓存会更有助于理解。 为啥会有两次写?必要了解partial page write 问题 : ... -
MySQL8.0新特性
2021-02-02 01:30:36本次的版本更新,在功能上主要...用户的创建与授权在MySQL5.7的版本:> grant all privileges on *.* to '用户名'@'主机' identified by '密码';在MySQL8.0需要分开执行:>create user '用户名'@'主机' ident... -
MySQL三大范式
2021-06-20 16:49:40数据表的每一列都要保持它的原子特性,也就是列不能再被分割。 第二范式(2NF) 概率:属性必须完全依赖于主键。 下满这张表不符合第二范式的要求。 依赖 在数据表中,属性(属性组)X确定的情况下,能完全退... -
浅谈MySQL系统特性
2021-01-26 04:47:00众所周知,MySQL是目前世界上最流行的关系型数据库管理系统之一,在WEB应用方面,MySQL是最好的RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。我们不得不承认,MySQL能够取得...