MySql事务原理

数据库事务

数据库事务在日常的作业中可或缺,我们了解事务只是停留在上课时候的事物的几种特性:原子性、隔离性、一致性、持久性,也知道数据库会有一个默认的隔离级别,那么为什么要有四种特性,以及默认的隔离级别的作用(可能会清楚是避免幻读等等,今天看了一些相关的文章谈一下自己的看法。

事务的基本要素(ACID)

原子性(Atomicity):事务内的操作要嘛全部完成,要嘛全部回滚。

一致性(Consistency):事务执行的前后都是合法的数据状态,不会违反任何的数据完整性。

隔离性(Isolation):主要是事务之间的相互的影响,根据隔离有不同的影响效果。

持久性(Durability):事务一旦提交,就会体现在数据库上,不能回滚。

事务并发的问题

脏读:比如事务A执行的过程中,读到了事务B未提交的内容。

不可重复度:指一个事务在前后两次查询的结果不一致。

幻读:幻读是指前后两次相同条件下的查询,后一次查询读到了前一次查询没有的行数据。

事务的隔离级别

隔离性与一致性是事务的特性,之所以要将其放在一起,是因为这两种特性相互制约,所以如何平衡他们之间的GAP需要我们自身的经验去判断。那为什么这么说呢,上文说过,对于单个事务来说甚至隔离性都不需要,但是对于多个事务并行执行的大场景来说,如果不用的事务对数据库同一数据进行读写,那么一致性就容易造成破坏,所以事务的隔离级别,意味着事务的并发处理是不一样,而不同的并发处理方式对于数据库的一致性是有影响的。那么就来说一说,不同的隔离级别是如何影响事务之间的并发程度的:

RAED UNCOMMITED:读未提交,任何操作都不加锁,所以能读到其他事务修改但未提交的数据行,也称之为脏读(Dirty Read);
READ COMMITED:读操作不加锁,写操作加锁。读被加锁的数据时,读事务每次都读undo log中的最近版本,因此可能对同一数据读到不同的版本(不可重复读),但能保证每次都读到最新的数据(事务提交之后的,不可重复读,两次读不一致),但是不会在记录之间加间隙锁,所以允许新的记录插入到被锁定记录的附近,所以再多次使用查询语句时,可能得到不同的结果(Non-Repeatable Read);
REPEATABLE READ:第一次读数据的时候就将数据加行锁(共享锁),使其他事务不能修改当前数据,即可实现可重复读。但是不能锁住insert进来的新的数据,当前事务读取或者修改的同时,另一个事务还是可以insert提交,造成幻读;
(注:mysql的可重复读的隔离级别解决了 “不可重复读” 和 “幻读” 2个问题,因为使用了间隙锁,下文讲解)
SERIALIZABLE:InnoDB 锁表,读锁和写锁阻塞,强制事务串行执行,解决了幻读的问题;
可见不同的隔离级别,对于读写事务是否加锁进行了限定,而不同的锁,对于数据库的事务的并发性能的影响,是不一样的,这里对于性能、一致性进行了对比,由此看出他们之间的关系:
性能:读未提交>读提交>可重复读>串行化
一致性:串行化>可重复读>读提交>读未提交

事务的ACID实现原理

  • 原子性:通过上面我们知道原子性是指一系列操作要么全做要么不做,在mysql数据库中事务的原子性是通过undo日志以及undo日志执行缓冲区来实现的,undo日志记录了事务执行前的值,如果在事务提交之前崩溃了就可以执行undo日志来回滚,另外undo日志还可以执行回滚等操作。
  • 持久性:持久性指的是事务一旦执行中,如果发生意外情况下数据不会丢失,redo日志记录数据修改后的值,可以避免数据在事务提交之前必须写入到磁盘的需求,减少I/O,而且redo日志只顺序记录了修改设计的值,保存自己涉及到的页极大提升了持久化的效率。
  • 隔离性:数据库事务的隔离性实现起来比较复杂,设计到了MVCC,数据库锁以及mysql视图,这里不做详细描述。
  • 一致性:我们知道一致性是指数据在事务前后保持一致,与其他事务特性不同的是事务的一致性实现依赖于事务的另外三个特性,另外我们还要在应用中保持一致性,因为在不同场景下一致性的定义不同,如在转账前后要保持总金额一样,在比如在缴费的时候我们要保障我们余额大于零。
本站运行时间: 0天 0小时 00分00秒

Copyright © 2020 过去的,未来的

Powered by Halo • Theme by Subtle Galaxy • REFERENCE FROM 寒山

Back to the top