大家好,欢迎来到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的解释如下
三.幻读
什么是幻读,如下:
InnoDB实现的RR通过mvcc机制避免了这种幻读现象
另一种幻读
姑且把左边的事务命名为事务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