MySQL事务隔离级别(InnoDB)

 

MySQL(InnoDB引擎)有四种事务隔离级别,从上到下安全性越来越高,性能越来越不好

读未提交(read uncommitted)

读已提交(read committed)

可重复读(repeatable read)

串行化(serializable)

MySQL默认的事务隔离级别为 可重复读

 

设置事务隔离级别基本命令:

查看MySQL数据库的当前事务隔离级别:select @@tx_isolation;   #REPEATABLE-READ  可重复读

设置当前会话隔离级别为 可重复读: set session transaction isolatin level repeatable read;

设置系统当前隔离级别为 可重复读: set global transaction isolation level repeatable read;

查看数据库当前自动提交状态: show variables like 'autocommit';  # 结果为on表示开启自动提交,为off表示关闭自动提交

更改数据库自动提交状态: set autocommit=off;  #设置为非自动提交,需要手动执行 commit 命令

 

事务的基本要素(ACID)

1、原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。

2、一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。

3、隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。

4、持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。

 

MySQL事务隔离级别

事务隔离级别    脏读    不可重复读    幻读
读未提交                    会               会
读已提交          不会                        会
可重复读          不会        不会             会 (InnoDB默认的事务隔离级别)
串行化             不会        不会           不会

 

事务的并发问题

假设同时开启A,B两个事务(前提需要设置事务为非自动提交:set autocommit=off),两个事务操作同一个数据库中的同一张表: USER(表的ID是唯一主键,因为幻读需要用到主键)

脏   读:事务A在USER表中插入一条数据 xxx, 未提交(也就是未执行commit命令),事务B读取USER表数据时会读到事务A插入的数据 xxx,  然后事务A发现插入的那条xxx数据有问题时执行回滚操作(rollback),事务B再次读取USER表数据的时候会发现被事务A回滚的数据 xxx不见了,这就是脏读。(读取到了未提交的事务)


不可重复读事务A在USER表中插入一条数据 xxx, 未提交(也就是未执行commit命令),事务B读取USER表数据时读取不到事务A插入的那条数据 xxx,事务A提交(执行commit命令)后,事务B再次读取USER表数据时会读取到事务A插入的那条数据 xxx。 这就是不可重复读。(事务提交前与事务提交后读取到的内容不一致,只读取已提交的数据)


幻    读:事务A在USER表中插入一条数据 xxx(主键为99), 未提交(也就是未执行commit命令),事务B读取USER表数据时读取不到事务A插入的那条数据 xxx(主键为99), 事务A提交(执行commit命令)后,事务B再次读取USER表数据时还是读取不到事务A插入的那条数据 xxx(主键为99)。但是当事务B想要在USER表中插入一条主键为99的记录时, 会报错 Duplicate entry '99' for key 'PRIMARY',这就是幻读。(读不到已提交的事务,但是也无法写入相同数据)

 

读未提交 - 对应脏读

读已提交 - 对应不可重复读

可重复读 - 对应幻读

串行化 我们来单独解释下,serializable隔离级别的多个事务不可以同时对同一张表修改 ,就是指读写都会上锁,所以效率会低。

同上,事务A,B同时开启,事务A在USER表中新增数据xxx,未执行commit命令,事务B开始执行查询USER表,这时候事务B查询是没有结果的,需要等事务A执行完commit释放写锁后,事务B的查询语句才会拿到读锁开始执行,结果自动返回。

 

 posted on 2020-03-11 13:11  阿叮339  阅读(289)  评论(0编辑  收藏  举报