巧记事务的隔离级别

185 阅读4分钟

巧记事务的隔离级别

什么事事务的隔离性

我们知道MySQL是一个客户端/服务器架构的软件,对于同一个服务器来说,可以有若干个客户端与之连接,每个客户端与服务器连接上之后,就可以称之为一个会话(Session)。每个客户端都可以在自己的会话中向服务器发出请求语句,一个请求语句可能是某个事务的一部分,也就是对于服务器来说可能同时处理多个事务。在事务简介的章节中我们说过事务有一个称之为隔离性的特性,理论上在某个事务对某个数据进行访问时,其他事务应该进行排队,当该事务提交之后,其他事务才可以继续访问这个数据。但是这样子的话对性能影响太大,我们既想保持事务的隔离性,又想让服务器在处理访问同一数据的多个事务时性能尽量高些,鱼和熊掌不可得兼,舍一部分隔离性而取性能者也。

事务隔离性解决的问题

事务隔离性解决问题排序:脏写 > 脏读 > 不可重复读 > 幻读

脏写

事务1修改了事务2正在修改的数据。

脏读

事务1读取到了事务2已结修改了的然后没有提交的数据,然后事务2数据回滚。

不可重复度

一个事务只能读到另一个已经提交的事务修改过的数据,并且其他事务每对该数据进行一次修改并提交后,该事务都能查询得到最新值。(==读取到了修改的数据==)

幻读

一个事务先根据某些条件查询出一些记录,之后另一个事务又向表中插入了符合这些条件的记录,原先的事务再次按照该条件查询时,能把另一个事务插入的记录也读出来。(==读取到了新增的数据==)

事务中的隔离级别

事务中的隔离级别由低到高依次分为:READ UNCOMMITTED(未提交读)>READ COMMITTED(已提交)>REPEATABLE READ(可重复读)>SERIALIZABLE(可串行化)。mysql中默认的隔离级别是可重复度 ,oracle默认的隔离级别是提交读

SQL标准中规定,针对不同的隔离级别,并发事务可以发生不同严重程度的问题,具体情况如下:

xxmm

mysql如何避免这些隔离性问题

如何解决脏写

在任何隔离级别下都不允许发生脏写,对一条数据修改时候都会对数据进行加锁。

如何解决脏读

事务只能读取其他事务已经提交的数据

如何解决不可重复读

MYSQL在解决不可重复读问题的时候,采用了MVCC给每行记录一个事务ID,然后在开启一个事务读取数据的时候也可以生成一个新的事务ID,并且生成一个readview存储当前的事务信息,读取数据的时候只能读取已经提交的事务ID,并且事务ID比当前事务ID小。在同一个事务内,每查询一次数据会生成一个新的readview,所以在查询之间有事务提交并且事务ID小于当前事务ID,所以就会造成不可重复读。所以解决不可重复读,也就是我们的可重复读,,只是在第一次查询的时候会生成一个readview,后面不会生成readview所以不会更新事务ID,也就不会产生不可重复读。

如何解决幻读

MYSQL在解决幻读的时候,是通过间隙锁解决的,在增加间隙锁的时候,其他数据在此范围内增加不进来,也就解决了幻读。

什么事ReadView

ReadView分为四部分信息组成:m_idsmin_trx_id,max_trx_id,creator_trx_id.

  • m_ids:表示在生成ReadView时当前系统中活跃的读写事务的事务id列表。
  • min_trx_id:表示在生成ReadView时当前系统中活跃的读写事务中最小的事务id,也就是m_ids中的最小值。
  • max_trx_id:表示生成ReadView时系统中应该分配给下一个事务的id值。
  • creator_trx_id:表示生成该ReadView的事务的事务id。