数据库的隔离级别

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

大家好,欢迎来到IT知识分享网。

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

事务的隔离级别 脏读 不可重复读 幻读
读未提交(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快照读

对于会对数据修改的操作(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操作会加行锁。

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

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/126542.html

(0)
上一篇 2025-09-17 21:10
下一篇 2025-09-17 21:20

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信