数据库的隔离级别

一.数据库事务的隔离级别

Read Uncommitted(未提交读)
在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。读取未提交的数据,也被称之为脏读(Dirty Read)。该级别用的很少。

Read Committed(提交读)
这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变,换句话说就是事务提交之前对其余事务不可见。这种隔离级别也支持不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select查询可能返回不同结果。

Repeatable Read(可重复读)
这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题(mysql彻底解决了幻读问题?请往下看)。

Serializable(可串行化)
这是最高的隔离级别,它强制事务都是串行执行的,使之不可能相互冲突,从而解决幻读问题。换言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。

事务的隔离级别脏读不可重复读幻读
读未提交(Read Uncommitted)
读已提交(Read Committed)
可重复读(Repeatable Read)
串行化(Serializable)

在Mysql的众多引擎中,只有innodb支持事务,这里面的事务隔离级别指的是innodb下的事务隔离级别

  • 查看mysql数据事务隔离级别:show variables like ‘tx_isolation’;
  • 设置事务隔离级别:set tx_isolation=‘REPEATABLE-READ’;

二.mysql怎么实现的可重复读

**MVCC多版本并发控制(Multi-Version Concurrency Control)**是MySQL中基于乐观锁理论实现隔离级别的方式,用于实现读已提交和可重复读取隔离级别。

在高性能MYSQL中对MVCC的解释如下

img

三.幻读

什么是幻读,如下:

img

InnoDB实现的RR通过mvcc机制避免了这种幻读现象

另一种幻读

img

姑且把左边的事务命名为事务A,右边的命名为事务B。
事务B执行后,在事务A中查询没有查到B添加的数据行,这就是可重复读。
但是,在事务A执行了update后,再查询时就查到了事务A中添加的数据,这就是幻读。
这种结果告诉我们其实在MySQL可重复读的隔离级别中并不是完全解决了幻读的问题,而是解决了读数据情况下的幻读问题。而对于修改的操作依旧存在幻读问题,就是说MVCC对于幻读的解决是不彻底的。

原以为这个是一种幻读,但这个只是对数据的修改操作(update insert delete)当前读的操作,他其实不是幻读

快照读和当前读

出现了上面的情况我们需要知道为什么会出现这种情况。在查阅了一些资料后发现在RR级别中,通过MVCC机制,虽然让数据变得可重复读,但我们读到的数据可能是历史数据,不是数据库最新的数据。这种读取历史数据的方式,我们叫它快照读 (snapshot read),而读取数据库最新版本数据的方式,叫当前读 (current read)。

select快照读

当提交select操作innodb默认会进行快照读,会记录下这次select后的结果,之后select 的时候就会返回这次快照的数据,即使其他事务提交了不会影响当前select的数据,这就实现了可重复读了。快照的生成当在第一次执行select的时候,也就是说假设当A开启了事务,然后没有执行任何操作,这时候B insert了一条数据然后commit,这时候A执行 select,那么返回的数据中就会有B添加的那条数据。之后无论再有其他事务commit都没有关系,因为快照已经生成了,后面的select都是根据快照来的。
当前读

对于会对数据修改的操作(update、insert、delete)都是采用当前读的模式。在执行这几个操作时会读取最新的版本号记录,写操作后把版本号改为了当前事务的版本号,所以即使是别的事务提交的数据也可以查询到。假设要update一条记录,但是在另一个事务中已经delete掉这条数据并且commit了,如果update就会产生冲突,所以在update的时候需要知道最新的数据。也正是因为这样所以才导致幻读。

四.如何解决幻读

在快照读情况下,mysql是通过mvcc来避免幻读

在当前读情况下,mysql通过X锁或next-key来避免其他事务修改:

  • 使用串行化读的隔离级别
  • (update、delete)当where条件为主键时,通过对主键索引加record locks(索引加锁/行锁)处理幻读。
  • (update、delete)当where条件为非主键索引时,通过next-key锁处理。next-key是record locks(索引加锁/行锁) 和 gap locks(间隙锁,每次锁住的不光是需要使用的数据,还会锁住这些数据附近的数据)的结合。

五.锁分类

  • 从性能来分乐观锁悲观锁

  • 从对数据库操作的类型来看,分为读锁和写锁(都属于悲观锁)

    • 读锁(共享锁,S锁(shared)):针对于同一份数据,多个读操作可以同时进去且不受影响。
    • 写锁(排他锁,X锁(XEclusive)):当前写操作没有完成之前,它会阻断其他的写锁和读锁。
  • 从数据上来看,分为行锁表锁

    • 行锁:每次操作锁住一行数据。开销大,加锁慢,会出现死锁;锁表颗粒度小,发生锁冲突概率最低,并发度最高。

    • 表锁:每次操作锁住整张表。开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低;

      一般用在整表数据迁移的场景

六.mysql引擎

InnoDB与MYISAM的最大不同有两点:

  • InnoDB支持事务(TRANSACTION)

  • InnoDB支持行级锁

InnoDB的行锁是针对索引加的锁,不是针对记录加的锁。并且该索引不能失效,否则都会从行锁升级为表锁

锁优化建议

  • 尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁

  • 合理设计索引,尽量缩小锁的范围

  • 尽可能减少检索条件范围,避免间隙锁(锁索引的范围)

  • 尽量控制事务大小,减少锁定资源量和时间长度,涉及事务加锁的sql尽量放在事务最后执行

  • 尽可能低级别事务隔离

总结:

MyISAM在执行查询语句SELECT前,会自动给涉及的所有表加读锁,在执行update、insert、delete操作会自动给涉及的表加写锁。InnoDB在执行查询语句SELECT时(非串行隔离级别),不会加锁。但是update、insert、delete操作会加行锁。

简而言之,就是读锁会阻塞写,但是不会阻塞读。而写锁则会把读和写都阻塞

  • 29
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL 数据库隔离级别主要用于控制事务处理的并发度和一致性,主要分为四个级别: 1. **读未提交(READ UNCOMMITTED)**: 这是最宽松的隔离级别,允许读取到其他事务尚未提交的数据。这可能导致数据一致性问题,如脏读、不可重复读和幻读。 2. **读已提交(READ COMMITTED)**: 只能读取到其他事务已经提交了的数据。避免了脏读,但由于更新操作可能会导致不可重复读和幻读的情况。 3. **可重复读(REPEATABLE READ)**: 保证在同一事务内的查询结果始终一致,即查询结果不会受到其他事务的影响。可以防止脏读和不可重复读,但仍然可能出现幻读情况。 4. **序列化(SERIALIZABLE)**: 此级别提供最高程度的隔离性,所有的事务按照固定的顺序逐一执行,完全避免了脏读、不可重复读和幻读问题,但是它通常会影响性能并限制并发能力。 为了改变 MySQL 数据库的默认隔离级别,在 SQL 查询中使用 `SET` 命令即可: ```sql SET SESSION TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE]; ``` 例如,将当前会话的隔离级别设置为可重复读: ```sql SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; ``` 更改隔离级别的影响因素包括但不限于数据库配置文件中的设置(例如通过 `my.cnf` 或者 `my.ini`),以及在需要时手动调整每个会话的隔离级别
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值