MySQL事务
系列文章
一、什么是事务
二、事务四大特征
1. 原子性
2. 一致性
3. 隔离性
4. 持久性
三、事务并发会出现的问题
1. 脏读
2. 不可重复读
3. 幻读
4. 区别
四、事务日志以及事务异常如何应对
1. 重做日志(redo log)(持久性实现原理)
2. 服务器异常停止对事务如何应对(事务写入过程)
3. 回滚日志(undo log)(原子性实现原理)
五、锁机制
1. 行锁
2. 表锁
3. 如何加锁
六、总结
————————————————
关于学习这件事情宁可花点时间系统学习,也不要东一榔头西一棒槌,都说学习最好的方式就是系统的学习,希望看完本文会让你对事务有一定的理解。数据库版本为8.0
系列文章
一、什么是事务
事务是独立的工作单元,在这个独立工作单元中所有操作要么全部成功,要么全部失败。
也就是说如果有任何一条语句因为崩溃或者其它原因导致执行失败,那么未执行的语句都不会再执行,已经执行的语句会进行回滚操作,这个过程被称之为事务。
例:
最近在写一个论坛系统,当发布的主题被其它用户举报后,后台会对举报内容进行审核。
一经审核为违规主题,则进行删除主题的操作,但不仅仅要删除主题还要删除主题下的帖子、浏览量,关于这个主题的一切信息都需要进行清理。
删除流程如下,用上边概念来说,以下执行的四个流程,每个流程都必须成功否则事务回滚返回删除失败。
假设执行到了第三步后SQL执行失败了,那么第一二步都会进行回滚,第四步则不会在执行。
二、事务四大特征
事务的四大特征,原子性、一致性、隔离性、持久性。
1. 原子性
事务中所有操作要么全部成功,要么全部失败,不会存在一部分成功,一部分失败。
这个概念也是事务最核心的特性,事务概念本身就是使用原子性进行定义的。
原子性的实现是基于回滚日志实现(undo log),当事务需要回滚时就会调用回滚日志进行SQL语句回滚操作,实现数据还原。
2. 一致性
一致性,字面意思就是前后一致呗!在数据库中不管进行任何操作,都是从一个一致性转移到另一个一致性。
当事务结束后,数据库的完整性约束不被破坏。
当你了解完事务的四大特征之后就会发现,都是保证数据一致性为最终目标存在的。
在学习事务的过程中大家看到最多的案例就是转账,假设用户A与用户B余额共计1000,那么不管怎么转俩人的余额自始至终也就只有1000。
3. 隔离性
保证事务执行尽可能的不受其它事务影响,这个是隔离级别可以自行设置,在innodb中默认的隔离级别为可重复读(Repeatable Read)。
这种隔离级别有可能造成的问题就是出现幻读,但是使用间隙锁可以解决幻读问题。
学习了隔离性你需要知道原子性和持久性是针对单个事务,而隔离性是针对事务与事务之间的关系。
4. 持久性
持久性是指当事务提交之后,数据的状态就是永久的,不会因为系统崩溃而丢失。
事务持久性是基于重做日志(redo log)实现的。
三、事务并发会出现的问题
1. 脏读
读取了另一个事务没有提交的数据。
以上表为例,事务A读取主题访问量时读取到了事务B没有提交的数据150。
如果事务B失败进行回滚,那么修改后的值还是会回到100。
然而事务A获取的数据是修改后的数据,这就有问题了。
2. 不可重复读
事务读取同一个数据,返回结果先后不一致问题。
上表格中,事务A在先后获取主题访问量时,返回的数据不一致。
也就是说在事务A执行的过程中,访问量被其它事务修改,那么事务A查询到的结果就是不可靠的。
**脏读与不可重复读的区别**
脏读读取的是另一个事务没有提交的数据,而不可重复读读取的是另一个事务已经提交的数据。
3. 幻读
事务按照范围查询,俩次返回结果不同。
以上表为例,当对100-200访问量的主题做统计时,第一次找到了100个,第二次找到了101个。
4. 区别
脏读读取的是另一个事务没有提交的数据,而不可重复读读取的是另一个事务已经提交的数据。
幻读和不可重复读都是读取了另一条已经提交的事务(这点与脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。
针对以上的三个问题,产生了四种隔离级别。
在第二节中对隔离性进行了简单的概念解释,实际上的隔离性是很复杂的。
在MySQL中定义了四种隔离级别,分别为未提交读 (Read Uncommitted)、提交读 (Read committed)、可重复读取 (Repeatable Read)、可串行化 (Serializable)。
未提交读 (Read Uncommitted):俩个事务同时运行,有一个事务修改了数据,但未提交,另一个事务是可以读取到没有提交的数据。这种情况被称之为脏读。
提交读(Read committed):一个事务在未提交之前,所做的任何操作其它事务不可见。这种隔离级别也被称之为不可重复读。因为会存在俩次同样的查询,返回的数据可能会得到不一样的结果。
可重复读(Repeatable Read):这种隔离级别解决了脏读问题,但是还是存在幻读问题,这种隔离界别在MySQL的innodb引擎中是默认级别。MySQL在解决幻读问题使用间隙锁来解决幻读问题。
可串行化 (Serializable):这种级别是最高的,强制事务进行串行执行,解决了可重复读的幻读问题。
对于隔离级别,级别越高并发就越低,而级别越低会引发脏读、不可重复读、幻读的问题。
因此在MySQL中使用可重复读(Repeatable Read)作为默认级别。
作为默认级别是如何解决并处理相应问题的呢!
那么针对这一问题,是一个难啃的骨头,咔咔将在下一期MVCC文章专门来介绍这块。