Mysql事务隔离性与相关锁的总结

事务隔离级别

隔离级别 脏读 不可重复读 幻读
读未提交 可以出现 可以出现 可以出现
读提交 不允许出现 可以出现 可以出现
可重复读 不允许出现 不允许出现 可以出现
序列化 不允许出现 不允许出现 不允许出现

注意点

上述隔离级别都是这么定义的,但是InnoDB和Falcon存储引擎已经通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了幻读问题。

已提交读 ReadCommitted 读取 不加锁 写入 加行锁(如果按索引过滤,那么只对筛选数据进行加行锁,但是如果不是按索引进行过滤,就对所有记录加行锁(但是Mysql对此进行了优化,会将不满足条件的记录释放锁))
可重复读 RepeatableRead

锁的类型

InnoDB 实现了两种类型的行级锁:

  • 共享锁

    (也称为 S 锁):允许事务读取一行数据。

    可以使用 SQL 语句 select * from tableName where … lock in share mode; 手动加 S 锁。

  • 独占锁

    (也称为 X 锁):允许事务删除或更新一行数据。

    可以使用 SQL 语句 select * from tableName where … for update; 手动加 X 锁。

S 锁和 S 锁是兼容的,X 锁和其它锁都不兼容,举个例子,事务 T1 获取了一个行 r1 的 S 锁,另外事务 T2 可以立即获得行 r1 的 S 锁,此时 T1 和 T2 共同获得行 r1 的 S 锁,此种情况称为锁兼容,但是另外一个事务 T2 此时如果想获得行 r1 的 X 锁,则必须等待 T1 对行 r 锁的释放,此种情况也成为锁冲突

为了实现多粒度的锁机制,InnoDB 还有两种内部使用的意向锁,由 InnoDB 自动添加,且都是表级别的锁。

  • 意向共享锁(IS):事务即将给表中的各个行设置共享锁,事务给数据行加 S 锁前必须获得该表的 IS 锁。
  • 意向排他锁(IX):事务即将给表中的各个行设置排他锁,事务给数据行加 X 锁前必须获得该表 IX 锁。

意向锁的主要目的是为了使得行锁表锁共存。表 2 列出了行级锁和表级意向锁的兼容性。

行级锁和表级意向锁的兼容性

锁类型 X IX S IS
X 冲突 冲突 冲突 冲突
IX 冲突 兼容 冲突 兼容
S 冲突 冲突 兼容 兼容
IS 冲突 兼容 兼容 兼容

行锁的算法

InnoDB 存储引擎使用三种行锁的算法用来满足相关事务隔离级别的要求。

  • Record Locks

    该锁为索引记录上的锁,如果表中没有定义索引,InnoDB 会默认为该表创建一个隐藏的聚簇索引,并使用该索引锁定记录。

  • Gap Locks

    该锁会锁定一个范围,但是不括记录本身。可以通过修改隔离级别为 READ COMMITTED 或者配置 innodb_locks_unsafe_for_binlog 参数为 ON

  • Next-key Locks

    该锁就是 Record Locks 和 Gap Locks 的组合,即锁定一个范围并且锁定该记录本身。InnoDB 使用 Next-key Locks 解决幻读问题。需要注意的是,如果索引有唯一属性,则 InnnoDB 会自动将 Next-key Locks 降级为 Record Locks。举个例子,如果一个索引有 1, 3, 5 三个值,则该索引锁定的区间为 (-∞,1], (1,3], (3,5], (5,+ ∞)

一致性非锁定读和多版本并发控制

一致性非锁定读(consistent nonlocking read)是指InnoDB通过行多版本控制(Multi Version Concurrency Control, MVCC)的方法来读取当前执行时间数据库中行的数据。

即如果读取的行正在执行变更操作,这时读取不会等待行锁的释放,而是会读取行的一个快照数据。快照是指该行的一个历史数据,通过undo操作来完成。这种方式极大提高了数据库的并发性,这也是InnoDB的默认设置。

快照是当前行的一个历史版本,但可能存在多个版本,行数据存在多个快照数据,这种技术成为行多版本技术,由此带来的并发控制,称为多版本并发控制(MVCC)。InnoDB在READ COMMITED 和 REPEATABLE READ隔离级别时,会使用非锁定的一致性读,但是在这两种隔离级别使用的快找数据定义却不同:

  • READ COMMITED: 总是读取最新一份快照
  • REPEATABLE READ: 总是读取事务开始时的行数据版本

我们执行一个示例:

一致性非锁定读
时间 会话A 会话B
1 BEGIN
2 select * from z where a = 3;
3 BEGIN
4 update z set b=2 where a=3;
5 select * from z where a = 3;
6 COMMIT;
7 select * from z where a = 3;
8 COMMIT;

在这个例子中我们可以清晰的看到0、1、2三种隔离级别的区别:

#在事务开始前我们可以分别调整为0、1、2三种隔离级别,来查看不同的输出
mysql> set session transaction isolation level READ UNCOMMITTED;
Query OK, 0 rows affected (0.00 sec)

mysql> select @@tx_isolation;
+------------------+
| @@tx_isolation   |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set (0.00 sec)

# A会话:T1事务
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from z where a = 3;
+---+------+
| a | b    |
+---+------+
| 3 |    1 |
+---+------+
1 row in set (0.00 sec)

# B会话:T2事务
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update z set b=2 where a=3;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

# A会话:T1事务,如果此时隔离级别是READ-UNCOMMITTED,因为此刻事务2可能会回滚,所以出现了脏读
mysql> select * from z where a=3;
+---+------+
| a | b    |
+---+------+
| 3 |    2 |
+---+------+
1 row in set (0.00 sec)

# A会话:T1事务,如果此时隔离级别是大于READ-UNCOMMITTED的更高级别
mysql> select * from z where a=3;
+---+------+
| a | b    |
+---+------+
| 3 |    1 |
+---+------+
1 row in set (0.00 sec)

# B会话:T2事务
mysql> commit;
Query OK, 0 rows affected (0.00 sec)

# A会话:T1事务,如果此时隔离级别是READ-COMMITTED,因为数据和事务开始时读取的出现了不一致,因此称为不可重复读,能够读到其他事务的结果,违反了事务的隔离性
mysql> select * from z where a=3;
+---+------+
| a | b    |
+---+------+
| 3 |    2 |
+---+------+
1 row in set (0.00 sec)

# A会话:T1事务,如果此时隔离级别是大于READ-COMMITTED的更高级别
mysql> select * from z where a=3;
+---+------+
| a | b    |
+---+------+
| 3 |    1 |
+---+------+
1 row in set (0.00 sec)

# A会话:T1事务
mysql> commit;
Query OK, 0 rows affected (0.00 sec)

一致性锁定读和SERIALIZABLE隔离

在默认的REPEATABLE READ隔离级别时,InnoDB使用的是一致性非锁定读。但有时我们也需要显示的指定使用一致性锁定读来保证读取操作时对数据进行加锁达到一致性。这要求数据库支持锁定读加锁语句:

  • select ... for update: 读取时对行记录加X锁
  • select ... lock in share mode:读取时对行记录加一个S锁

这两种锁必须在一个事务中,当事务提交后锁也就释放了,因此务必加上BEGIN, START TRANSACTION或者SET AUTOCOMMIT=0。

我们在前面隔离级别时也说过SERIALIZABLE隔离级别会对读操作自动加上LOCK IN SHARE MODE指令来加上一个共享锁,因此不再支持一致性的非锁定读。这也是隔离级别3的一大特性。

参考

MySQL 事务隔离级别和锁

MySQL的锁和事务隔离级别

原文地址:https://www.cnblogs.com/hongdada/p/12230580.html

时间: 2024-11-09 04:37:49

Mysql事务隔离性与相关锁的总结的相关文章

Mysql事务-隔离级别

MYSQL事务-隔离级别 事务是什么? 事务简言之就是一组SQL执行要么全部成功,要么全部失败.MYSQL的事务在存储引擎层实现. 事务都有ACID特性: 原子性(Atomicity):一个事务必须被视为一个不可分割的单元: 一致性(Consistency):数据库总是从一种状态切换到另一种状态: 隔离性(Isolation):通常来说,事务在提交前对于其他事务不可见: 持久性(Durablity):一旦事务提交,所做修改永久保存数据库: 事务最常用的例子就是银行转账.假设polo需给lynn转

Mysql事务隔离级别

在说Isolation之前,需要谈谈关系型数据库的ACID特性. A(atomicity,原子性),指一个事务要么完全完成,要么全部回滚到起始状态,不存在中间状态. C(Consistency,一致性),指在事务开始前与事务结束后,及在事务内部,数据的完整性结束不被破坏,即不存在新旧数据的混合情况.如在一个事务处理过程中,有些数据被其他事务修改,则在事务中要么只出现旧值,要么只出现新值,决不能是旧值混在该事务内. I(Isolation,隔离性),指事务在执行过程中互不干扰,也不能看到其他事务未

MySql 事务,并发问题 ,锁机制 <转>

Mysql事务,并发问题,锁机制 1.什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点. 原子性:要不全部成功,要不全部撤销 隔离性:事务之间相互独立,互不干扰 一致性:数据库正确地改变状态后,数据库的一致性约束没有被破坏 持久性:事务的提交结果,将持久保存在数据库中 2.事务并发会产生什么问题 1)第一类丢失更新:在没有事务隔离的情况下,两个事务都同时更新一行数据,但是第二个事务却中途失败退出, 导致对数据的两个修改都失效了. 例如: 张三的工资为5000,事务A中获取

查询mysql事务隔离级别

查询mysql事务隔离级别 查询mysql事务隔离级别 分类: DB2011-11-26 13:12 2517人阅读 评论(0) 收藏 举报 mysqlsessionjava 1.查看当前会话隔离级别 select @@tx_isolation; 2.查看系统当前隔离级别 select @@global.tx_isolation; 3.设置当前会话隔离级别 set session transaction isolatin level repeatable read; 4.设置系统当前隔离级别 s

MySQL事务隔离级别为"REPEATABLE-READ"下的"幻读"现象

MySQL事务隔离级别为"REPEATABLE-READ"下的"幻读"现象 关于mysql命令行中事务控制的语句见该文章:http://my.oschina.net/xinxingegeya/blog/296459 本片参考文章:http://blog.csdn.net/jiao_fuyou/article/details/16368827 http://www.cnblogs.com/hancf/archive/2012/08/28/2660422.html my

mysql事务隔离界别与锁机制

数据库锁 共享锁(Shared lock) 例1: ---------------------------------------- T1: select * from table (请想象它需要执行1个小时之久,后面的sql语句请都这么想象) T2: update table set column1='hello' 过程:T1运行 (加共享锁) T2运行等待T1运行完之后再运行T2 之所以要等,是因为T2在执行update前,试图对table表加一个排他锁,而数据库规定同一资源上不能同时共存共

理解MySql事务隔离机制、锁以及各种锁协议

一直以来对数据库的事务隔离机制的理解总是停留在表面,其内容也是看一遍忘一边.这两天决定从原理上理解它,整理成自己的知识.查阅资料的过程中发现好多零碎的概念如果串起来足够写一本书,所以在这里给自己梳理一个脉络,具体的内容参考引文或在网上搜一下.由于平时接触最多的是MySQL,所以文章中某些部分是MySQL特有的特性,请读者注意. 数据库并发操作会引发的问题: 多个事务同时访问数据库时候,会发生下列5类问题,包括3类数据读问题(脏读,不可重复读,幻读),2类数据更新问题(第一类丢失更新,第二类丢失更

MySQL事务隔离级别和锁

表结构 create table record( id int auto_increment primary key, title varchar(255) not null, shortName varchar(255) not null, authorId int not null, createTime datetime not null, state int  not null, totalView int default null ); insert into record (titl

mysql事务隔离级别与锁的关系

其实操作了这么久mysql一直也没有把mysql中事务跟锁的关系弄得特别清楚.然后搜到美团这篇文章,顺便结合一下自己遇到的问题总结一下. 首先事务有四种隔离级别: Reference: http://tech.meituan.com/innodb-lock.html Innodb中的事务隔离级别和锁的关系