彻底搞清Mysql中的事务--事务的定义,特征,隔离级别,提交方式,实现的原理

-- 彻底搞清Mysql中的事务--事务的定义,特征,隔离级别,提交方式,实现的原理
【官网】:https://dev.mysql.com

应用场景

mysql 事务和锁是mysql中非常重要功能特性,为了避免操作或存取数据时出现幻读,脏读,脏写,不可重复读等问题,我们需要了解事务的特征,隔离级别,提交方式,原理等。

基础资源

mysql

使用须知

mysql 事务和锁是mysql中非常重要功能特性,为了避免操作或存取数据时出现幻读,脏读,脏写,不可重复读等问题,我们需要了解事务的特征,隔离级别,提交方式,原理等。

配置步骤


常见问题

快速入门

A)事务的定义.

事务是数据库管理系统(DBMS)执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成.

注:本文中涉及MySQL 事务都是指在 InnoDB 引擎下的事务,类似MyISAM 引擎是不支持事务的.

B)事务的基本特性.

关系型数据库中的事务都包含四大特性--原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)(统称:ACID)。
原子性(Atomicity) :是指对数据库的一系列操作,要么全部成功,要么全部失败,不可能出现部分成功的情况。(示例:以银行转账场景为例:一个账户的余额减少,另一个账户的余额增加,这两个操作必定是同时成功或者同时失败的)
一致性(Consistency) :是指数据库的完整性约束没有被破坏,在事务执行前后都是合法的数据状态。这里的一致可以表示数据库自身的约束没有被破坏,比如某些字段的唯一性约束、字段长度约束等等。
隔离性(Isolation) : 指的是多个事务彼此之间是完全隔离、互不干扰的。隔离性的最终目的也是为了保证一致性。
持久性(Durability):  是指只要事务提交成功,那么对数据库做的修改就被永久保存下来了(持久化了),不可能自动再回到原来的状态。

C)事务的状态.

活动的(active): 事务对应的数据库操作正在执行过程中,则该事务处于活动状态。
部分提交的(partially committed): 事务中的最后一个操作执行完成,但还未将变更刷新到磁盘时,则该事务处于部分提交状态。
失败的(failed): 事务处于活动或者部分提交状态时,由于某些错误导致事务无法继续执行,则事务处于失败状态。
中止的(aborted): 事务处于失败状态,且回滚操作执行完毕,数据恢复到事务执行之前的状态时,则该事务处于中止状态。
提交的(committed): 当事务处于部分提交状态,并且将修改过的数据都同步到磁盘之后,此时该事务处于提交状态。


D)事务要解决的一些问题.

1)脏读:一个事务读取到另一个事务中没有提交的数据;

【说明】:事务还没提交时被查询到的中间数据。    

2)不可重复读(虚读):在同一个事务中两次读取到的数据不一样;

【说明】事务未提交前查询的数据,并发的另外一个事务已抢先提交,原事务提交时发现数据不一样了。 

 3)幻读:一个事务操作(DML)数据表中所有的记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改;

【说明】:一个事务执行过程中,另外一个事务操作并提交了造成读取的结果和原来最初的明细不一致,对不上

E)事务的隔离级别.

SQL标准中设立了4种隔离级别,不同的隔离级别可以解决不同的读一致性问题.

其中事务隔离级别越高对应的安全性越高,事务的并发度就越低。由于InnoDB 在可重复读(REPEATABLE READ)的级别就解决了幻读的问题。这也是InnoDB使用可重复读 作为事务默认隔离级别的原因

1)读未提交(read uncommitted):

   注:有脏读、不可重复读、幻读问题 (不可重复读代表数据有但是修改了,幻读时数据刚刚有现在没)
         原因:未提交的数据可能会发⽣回滚,因此我们把该级别读取到的数据称之为脏数据,把这个问题称之为脏读.

2)READ COMMITTED:读已提交

注:可以解决脏读问题,但是存在不可重复读的问题
原因:在事务的执⾏中可以读取到其他事务提交的结果,所以在不同时间
的相同 SQL 查询中,可能会得到不同的结果,这种现象叫做不可重复读.

3)可重复读(repeatable read)

注:mysql默认隔离级别,解决不可重复读的问题,但是存在幻读问题.
原因:确保同⼀事务多次查询的
结果⼀致。但也会有新的问题,⽐如此级别的事务正在执⾏时,另⼀个事务成功的插⼊了某条数
据,但因为它每次查询的结果都是⼀样的,所以会导致查询不到这条数据,⾃⼰重复插⼊时⼜失败
(因为唯⼀约束的原因)。明明在事务中查询不到这条信息,但⾃⼰就是插⼊不进去,这就叫幻读
(Phantom Read)

4)SERIALIZABLE:序列化

注:事务的最⾼隔离级别,它会强制事务排序,使之不会发⽣冲突,从⽽解决
了脏读、不可重复读和幻读问题,但因为执⾏效率低,所以真正使⽤的场景并不多


[注1]数据库查询隔离级别:select  @@tx_isolation;

[注2]set global transaction isolation level 级别字符串。

F)事务的提交方式.

1)两种事务提交方式

自动提交:MySQL数据库默认是自动提交的,一条DML(增删改语句)能够自动提交一次事务;
手动提交:需要先开启事务(START TRANSACTION),再提交(COMMIT)或Rollback;

2)修改事务的默认提交方式

查看默认提交方式:SELECT @@autocommit; -- 1代表自动提交,0代表手动提交
修改默认提交方式:SET @@autocommit = 0; -- 1代表自动提交,0代表手动提交
注:手动控制事务的开启与提交,可以很大程度提高数据插入的效率,因此在进行数据大批量插入操作时可以结合手动控制事务提交方式来提高性能。

G)事务的实现原理.

1.事务的原子性是通过 undo log 来实现的.

   使用 undo log ,从而达到回滚.

2.事务的持久性性是通过 redo log 来实现的

    使用 redo log,从而达到故障后恢复

3.事务的隔离性是通过 (读写锁+MVCC)来实现的

使用锁以及MVCC,运用的优化思想有读写分离,读读并行,读写并行.

关于MVCC.

MVCC(Multi Version Concurrency Control),中文名是多版本并发控制,简单来说就是通过维护数据历史版本,从而解决并发访问情况下的读一致性问题。
版本链
在InnoDB中,每行记录实际上都包含了两个隐藏字段:事务id(trx_id)和回滚指针(roll_pointer)。
trx_id:事务id。每次修改某行记录时,都会把该事务的事务id赋值给trx_id隐藏列。
roll_pointer:回滚指针。每次修改某行记录时,都会把undo日志地址赋值给roll_pointer隐藏列。




关于锁.

共享锁(shared lock),又叫做"读锁";

读锁是可以共享的,或者说多个读请求可以共享一把锁读数据,不会造成阻塞。

排他锁(exclusive lock),又叫做"写锁";

写锁会排斥其他所有获取锁的请求,一直阻塞,直到写入完成释放锁。


4.事务的一致性是通过原子性,持久性,隔离性来实现的(事务最终目的是要确保数据的可靠性,一致性)

--通过回滚,以及恢复,和在并发环境下的隔离做到一致性.





参考资料