MySQL脏读、不可重复读、幻读

 

隔级别脏读不可重复读幻读
未提交读可能               可能可能
读已提交不可能可能可能
可重复读不可能不可能可能
串行不可能不可能不可能

可重复读与幻读区别:不可重复读的重点是修改;同样的条件,第1次和第2次读取的值不一样。幻读的重点在于新增或者删除;同样的条件, 第1次和第2次读出来的记录数不一样。从控制角度来看,不可重复读只需要锁住满足条件的记录,幻读要锁住满足条件及其相近的记录。

避免可重复读:通常可以用 set session transaction  isolation level repeatable read 来设置隔离级别,这样事务A 在两次读取表T中的数据时,事务B如果企图更改表T中的数据(细节到事务A读取数据)时,就会被阻塞,知道事务A提交! 这样就保证了,事务A两次读取的数据的一致性。

查看以及修改事务隔离级别:

查看事务隔离级别
show variables like 'transaction_isolation';
或者select @@transaction_isolation;
读未提交:
set transaction isolation level read uncommitted;
可重复读:
set session transaction  isolation level repeatable read

MySQL下的锁:

是网络数据库中的一个非常重要的概念,当多个用户同时对数据库并发操作时,会带来数据不一致的问题,所以,锁主要用于多用户环境下保证数据库完整性和一致性。

程序员角度分为两种:一种是悲观锁,一种乐观锁。

数据库系统角度分为三种:排他锁、共享锁、更新锁。

悲观锁按使用性质划分:共享锁(读锁,S锁),排它锁(写锁,X锁)

悲观锁按使用范围(锁的粒度)划分:表锁,页锁,行锁。

补充:

行锁 :锁的作用范围是行级别。表锁: 锁的作用范围是整张表。页锁: 介于两者之间

InnoDB :支持行锁和表锁(实际上InnoDB 是通过给索引项加锁,来实现行锁的)   Smicar :只支持表锁

锁的MySQL语句:

表锁:
读锁:lock tables t1 read;
写锁:lock tables t1 write;
解锁:unlock table;


行锁:
共享锁(s):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE
排他锁(x):SELECT * FROM table_name WHERE ... FOR UPDATE
解锁:
1.查询 正在执行的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;

2.杀死进程id(就是上面查询结果集的trx_mysql_thread_id列)
kill 线程ID
这样行锁锁定就解决了

查询mysql数据库中还可以使用:
查看正在锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
查看等待锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
查询mysql数据库中存在的进程
select * from information_schema.PROCESSLIST(show processlist;)


在默认的可重复读隔离级别下:

执行查询语句( SELECT )前,由于 MVCC(多版本控制)的方式,什么锁都不会加。

在执行更新操作( UPDATE、DELETE、INSERT 等)前,会自动给涉及的行加写锁,此时会阻塞其他用户的写操作,但是通过 MVCC(多版本控制)的方式允许读操作。

innodb下的记录锁(也叫行锁),间隙锁,next-key锁统统属于排他锁

MySQL InnoDB支持三种行锁定方式:InnoDB的默认加锁方式是next-key 锁。

行锁:记录锁其实很好理解,对表中的记录加锁,叫做记录锁,简称行锁。

next-key锁:其实包含了记录锁和间隙锁,即锁定一个范围,并且锁定记录本身,InnoDB默认加锁方式是next-key 锁。

MySQL InnoDB支持三种行锁定方式:InnoDB的默认加锁方式是next-key 锁。

1:行锁(Record Lock):锁直接加在索引记录上面,锁住的是key。

2:间隙锁(Gap Lock):锁定索引记录间隙,确保索引记录的间隙不变。间隙锁是针对事务隔离级别为可重复读或以上级别而已的。

3:Next-Key Lock :行锁和间隙锁组合起来就叫Next-Key Lock。 

当InnoDB扫描索引记录的时候,会首先对索引记录加上行锁(Record Lock),再对索引记录两边的间隙加上间隙锁(Gap Lock)。加上间隙锁之后,其他事务就不能在这个间隙修改或者插入记录。Gap Lock在InnoDB的唯一作用就是防止其他事务的插入操作,以此防止幻读的发生。

Innodb自动使用间隙锁的条件:

(1)必须在Repeatable Read级别下

(2)检索条件必须有索引(没有索引的话,mysql会全表扫描,那样会锁定整张表所有的记录,包括不存在的记录,此时其他事务不能修改不能删除不能添加) 

间隙锁的目的是为了防止幻读,其主要通过两个方面实现这个目的:

(1)防止间隙内有新数据被插入

(2)防止已存在的数据,更新成间隙内的数据(例如防止numer=3的记录通过update变成number=5)

总结;

间隙锁在InnoDB的唯一作用就是防止其它事务的插入操作,以此来达到防止幻读的发生,所以间隙锁不分什么共享锁与排它锁。 默认情况下,InnoDB工作在Repeatable Read隔离级别下,并且以Next-Key Lock的方式对数据行进行加锁,这样可以有效防止幻读的发生。Next-Key Lock是行锁与间隙锁的组合,当对数据进行条件,范围检索时,对其范围内也许并存在的值进行加锁!当查询的索引含有唯一属性(唯一索引,主键索引)时,Innodb存储引擎会对next-key lock进行优化,将其降为record lock,即仅锁住索引本身,而不是范围!若是普通辅助索引,则会使用传统的next-key lock进行范围锁定!

要禁止间隙锁的话,可以把隔离级别降为Read Committed,或者开启参数innodb_locks_unsafe_for_binlog。
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值