mysql事务隔离

时间:2022-04-02 02:04:43

在mysql中事务是在操作引擎上实现,常见引擎中InnoDB是支持事务的,而MyISAM不支持事务,下面所讲都是基于InnoDB的

事务是指一组操作要么全部成功要么全部失败;

事务的特性:ACID,这里不展开来讲解,只针对隔离性来讲解

隔离性:在多个事务同时存在的情况下,多个事务之间互不产生影响,当然这只是一种理想状态,在实际开发中并不会选择事务完全隔离,因为要做到事务完全隔离会引起数据库效率变低以及并发性能下降,mysql提供了不同的事务隔离级别,可根据不同的业务选择不同的事务隔离级别,mysql默认的隔离级别是可重复读。

事务并发导致的一些问题:

脏读:读到其他事务未提交的内容

不可重复读:在一个事务中,对同一个记录读到了不同的值(读到了更新操作)

虚度/幻读:在同一个事务中,读到不同的记录(读到了插入删除操作)

 

隔离级别:

读未提交:一个事务会读到其他事务未提交的内容(存在脏读)

读已提交:一个事务不会读到其他事务未提交的内容,其他事务只有提交后才会对当前事务可见(解决了脏读,存在不可重复读和幻读)

可重复读:一个事务在启动时和执行中读到的数据完全相同(解决了不可重复读,存在幻读(不一定https://www.cnblogs.com/likui360/p/9632641.html))

RR隔离级别保证对读取到的记录加锁 (记录锁),同时保证对读取的范围加锁,新的满足查询条件的记录不能够插入 (间隙锁),不存在幻读现象。

串行化:对同一行记录会加锁,读时加读锁,写时加写锁,当读写锁冲突时需要等到上一个事务执行完成才能执行(解决了所有问题)

事务隔离的实现:是基于视图和锁实现的

读未提交没用视图和锁;读已提交:在每个sql执行的时候就创建一个视图;可重复读:在每个事务开启的时候就创建一个视图(有问题,需要再确认)

事务回滚原理:

每条记录在更新的时候都会记录一条回滚操作,该回滚操作以日志的形式记录

当在日志之前没有read-view的时候就将该回滚日志删除(系统自动判断)

由于会记录回滚日志就需要避免使用长事务,因为长事务会占用大量的系统资源以及锁,可能会拖垮数据库

开启事务的方式:

对于一个MYSQL数据库(InnoDB),事务的开启与提交模式无非下面这两种情况:

1、若参数autocommit=0,事务则在用户本次对数据进行操作时自动开启,在用户执行commit命令时提交,用户本次对数据库开始进行操作到用户执行commit命令之间的一系列操作为一个完整的事务周期。若不执行commit命令,系统则默认事务回滚。总而言之,当前情况下事务的状态是自动开启手动提交。

2、若参数autocommit=1(系统默认值),事务的开启与提交又分为两种状态:

①手动开启手动提交:当用户执行start transaction命令时(事务初始化),一个事务开启,当用户执行commit命令时当前事务提交。从用户执行start transaction命令到用户执行commit命令之间的一系列操作为一个完整的事务周期。若不执行commit命令,系统则默认事务回滚。

②自动开启自动提交:如果用户在当前情况下(参数autocommit=1)未执行start transaction命令而对数据库进行了操作,系统则默认用户对数据库的每一个操作为一个孤立的事务,也就是说用户每进行一次操作系都会即时提交或者即时回滚。这种情况下用户的每一个操作都是一个完整的事务周期。