发布于 

MySQL-事务隔离级别

本站字数:106.9k    本文字数:1.1k    预计阅读时长:3min    访问次数:

事务有四大特性(ACID):原子性,一致性,隔离性和持久性。隔离性一般在事务并发的时候需要保证事务的隔离性,事务并发会出现很多问题,包括脏写,脏读,不可重复读,幻读等等情况。为了保证在不同的情况下都能有良好的隔离性,MySQL定义了四大事务隔离级别。

事务并发没有隔离导致的问题

事务在并发的过程中就会遇到很多问题,例如读取到其他事务尚未提交的数据,上一个时刻和当前时刻读取到不同的结果,其他事务新增记录以后,当前事务查询到的结果多了等等问题。这些问题都是多事务并发时期发生的问题。所以为了保证事务之间能够有比较好的隔离性,就需要划分事务隔离级别。

本节主要表写事务并发发生的各种问题。

脏写

事务A 修改了ID=2的字段c修改为2,事务B 也修改了ID=2的字段c修改为3。如果此时事务A发生了回滚,那么事务B的修改记录就发生了丢失,事务A脏写了事务B的数据。

这个时候MySQL给出的方案是,在数据被修改的时候加锁,这样就不会发生类似的问题了。事务A 修改了ID=2的字段c修改为2,事务A尚未提交的时候,事务B就会被阻塞,直到事务A被提交,或者回滚。

脏读

事务并发问题
事务并发问题

所谓的脏读就是读未提交,一个事务还没有提交的时候,它做的编程就能被其他事务看见。如果开启读未提交,那么按照上图,V1=2,V2=2,V3=2。

不可重复读

所谓的不可重复读,指的是在同一个事务执行期间,读到了不同的数据,重复读取同一个数据,读到不同的结果,就是发生了不可重复读的问题。例如,开启读已提交的隔离级别,就会发生不可重复读的问题。那么按照上图,V1=1,V2=2,V3=2。

幻读

所谓的幻读就是,事务新增记录以后,其他事务发现这个事务新增了某条记录,就是发生了幻读现象。对于幻读问题,可以对发生锁竞争的区域加锁,从而保证这个区域内不会新增数据,保证事务执行是串行化的。当然串行化可以保证不可重复读,但是原理和不可重复读的原理不一致,上面说到为了保证串行化需要对发生竞争的行或者区域加锁,那么不可重复读的原因就是发生了竞争,解决办法就是在事务A读写这行的时,加入读或者写锁,导致事务B阻塞无法继续执行,事务A结束,事务B在执行。串行化实质上就是一次只有一个事务在执行,这样牺牲了效率,但是换来了更高的隔离级别。

同样的,如果开启串行化的隔离级别以后,按照上图,V1=1,V2=2,V3=2。

事务隔离级别

上面已经或多或少提到了事务的隔离级别,事务的隔离级别一共有四种:读未提交(READ UNCOMMITED),读已提交(READ COMMITED),可重复读(REPEATABLE READ)和串行化(SERIALIZED)。

  • 读未提交(READ UNCOMMITED)

    一个事务还没有提交的时候,它所作的变更就能被其他的事务看到。

  • 读已提交(READ COMMITED)

    一个事务已经提交后,他做的变成才能被被其他事务看到。

  • 可重复读(REPEATED READ)

    一个事务的执行过程中看到的数据,总是和这个事务启动的时候看到的数据是一致的。

  • 可序列化(SIRIALIZABLE)

    对行加读写锁,出现锁冲突的时候,一个事务必须等另一个事务完成后才能继续执行。