Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

锁、脏读、不可重复读、幻读(基于MySQL InnoDB引擎5.6.40版本验证) #3

Open
diaosichengxuyuan opened this issue Jul 25, 2018 · 0 comments

Comments

@diaosichengxuyuan
Copy link
Owner

diaosichengxuyuan commented Jul 25, 2018

1.ACID特性

A:原子性 C:一致性 I:隔离性 D:持久性
事务的ACID是通过InnoDB日志和锁来保证。事务的隔离性是通过数据库锁的机制实现的,持久性通过redo log(重做日志)来实现,原子性和一致性通过Undo log来实现。UndoLog的原理很简单,为了满足事务的原子性,在操作任何数据之前,首先将数据备份到一个地方(这个存储数据备份的地方称为UndoLog)。然后进行数据的修改。如果出现了错误或者用户执行了ROLLBACK语句,系统可以利用Undo Log中的备份将数据恢复到事务开始之前的状态。
和Undo Log相反,RedoLog记录的是新数据的备份。在事务提交前,只要将RedoLog持久化即可,不需要将数据持久化。当系统崩溃时,虽然数据没有持久化,但是RedoLog已经持久化。系统可以根据RedoLog的内容,将所有数据恢复到最新的状态。

2.脏读、不可重复读、幻读、丢失更新

脏读: A事物读取到了B事物未提交的数据,称A读到的是脏数据,产生脏读。
不可重复读: 事务A首先读取了一条数据,然后执行逻辑的时候,事务B将这条数据改变了,然后事务A再次读取的时候,发现数据不匹配了,就是所谓的不可重复读了。
幻读: 事务A首先根据条件索引得到N条数据,然后事务B改变了这N条数据之外的M条或者增添了M条符合事务A搜索条件的数据,导致事务A再次搜索发现有N+M条数据了,就产生了幻读。
丢失更新: A和B事物同时读取一条数据,A事物将数据值改为M,B事物将数据改为N,最终的值变为N,A的修改丢失了。
注意: MySQL InnoDB引擎将上面描述的不可重复读称为不可重复读和幻读。

3.InnoDB引擎的不同隔离级别

READ-UNCOMMITTED:可能产生脏读、不可重复读、幻读
READ-COMMITTED:可能产生不可重复读、幻读
REPEATABLE-READ(默认):InnoDB默认隔离级别,可能产生幻读
SERIALIZABLE:最高隔离级别,不会出现幻读

4.通过多版本控制实现事物隔离

原理: 非锁定的一致性读,又称多版本控制(MVCC),上面示例中普通的select语句是不加锁的,数据库对每条记录会有多个版本的记录,在READ-UNCOMMITTED级别,有一个版本,任何事物不管是否提交都可以修改,读取时返回的就是这个版本,所以一个事物可能读取到另一个事物未提交的数据;在READ-COMMITTED级别,有一个版本,只有事物提交后才能更新到这个版本中,读取时返回的就是这个版本,所以可以防止脏读;在REPEATABLE-READ级别,有一个版本是事物开始时记录的状态,读取每次都返回这个版本,这样即使有事物修改并提交了数据,也不会影响到此版本,所以可以防止重复读。

(1)READ-UNCOMMITTED级别可导致脏读
image

(2)READ-COMMITTED级别可防止脏读
image

(3)READ-COMMITTED级别产生不可重复读
image

(4)REPEATABLE-READ级别可防止不可重复读
image

5.通过锁实现事物隔离

原理:
image
image

(1)READ-COMMITTED级别产生不可重复读
image

(2)REPEATABLE-READ级别可防止不可重复读
image

(3) SERIALIZABLE级别可防止幻读
image

6.本文中用到的命令

查看事物隔离级别
show variables like 'tx_isolation'
修改事物隔离级别
set session transaction isolation level read uncommitted/read committed/repeatable read/serializable

7.排查sql是否用到锁

(1)查看sql是否会用到锁:select for update/select in share mode/update/delete这些会用到锁,其他情况走多版本控制(MVCC)
(2)查看sql是否走索引:走索引用行锁、不走索引用表锁
(3)查看事物隔离级别:READ-COMMITTED记录锁 REPEATABLE范围锁

8.参考

https://www.cnblogs.com/duhuo/p/5650876.html
https://blog.csdn.net/canot/article/details/104925841

9.与MyISAM对比

MyISAM表锁是deadlock free的,这是因为MyISAM总是一次获得所需的全部锁,要么全部满足,要么等待,因此不会出现死锁。
InnoDB与MyISAM的最大不同有两点:一是支持事务;二是采用了行级锁。

作者原创,转载请注明出处,违法必究!

@diaosichengxuyuan diaosichengxuyuan changed the title 脏读、不可重复读、幻读(基于MySQL InnoDB引擎) 脏读、不可重复读、幻读(基于MySQL InnoDB引擎验证) Jul 25, 2018
@diaosichengxuyuan diaosichengxuyuan changed the title 脏读、不可重复读、幻读(基于MySQL InnoDB引擎验证) 脏读、不可重复读、幻读(基于MySQL InnoDB引擎5.6.40版本验证) Jul 25, 2018
@diaosichengxuyuan diaosichengxuyuan changed the title 脏读、不可重复读、幻读(基于MySQL InnoDB引擎5.6.40版本验证) 锁、脏读、不可重复读、幻读(基于MySQL InnoDB引擎5.6.40版本验证) Nov 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant