一.数据库事务的隔离级别
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的表明如下
三.幻读
什么是幻读,如下:
InnoDB实现的RR通过mvcc机制避免了这种幻读征象
另一种幻读
姑且把左边的事务定名为事务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操作会加行锁。
简而言之,就是读锁会壅闭写,但是不会壅闭读。而写锁则会把读和写都壅闭。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |