MySql(事务,锁)
事务是什么
事务是数据库一个不可以分隔的操作序列。在事务中执行的操作,会使结果从一个一致性状态到达另一个一致性状态。要么是产生操作结果,要么就是不产生结果
事务的四个特性(ACID)
- 原子性:一个事务是是一个执行单位,它要么就是全部执行,要么就是全部不执行。
- 一致性:事务执行的前后,多个事务对数据的读取是一致的。
- 隔离性:并发访问数据库是,一个事务中读取的数据是不受其他事务所影响的。
- 持久性:一个事务在提交之后,他作出的改变是持久的。
脏读
- 在一个事务中更新了一部分数据,这个时候另外一个事务读取了这一部分数据。而这个时候,第一个事务中回滚了数据,第二个事务中读取到的数据就是错误的了,这就是脏读。
幻读
- 在一个事务当中,两次查询的数据行数不一致。原因可能是在第一次读取后另外一个事务又插入了几行数据。
不可重复读
- 在一个事务当中,由于在两次查询中有另外一个事务更新了数据,所以导致两次查询的数据不一致。
事务隔离级别
-
READ-UNCOMMITTED(读取未提交): 读取尚未提交的数据,可能造成脏读,幻读,不可重复读
-
READ-COMMITTED(读取已提交): 读取已经提交的事务数据,能防止数据脏读,但仍然有可能会幻读,不可重复度。
-
REPEATABLE-READ(可重复读) 对数据同一个字段读取是保持一致的,当够避免脏读和不可重复读,但幻读依然可能存在。
-
SERIALIZABLE(可串行化): 事务最高隔离级别,允许事务串行化,完成一个事务再继续下一个事务。所有事务都是逐个执行,可以避免脏读,幻读,不可重复读。
MySql事务的隔壁界别是REPEATABLE-READ(可重复读),MySql的事务机制是基于锁机制和并发调度实现的,隔离级别越低,使用的锁就越少。InnoDB 存储引擎在 分布式事务 的情况下一般会用到**SERIALIZABLE(可串行化)**隔离级别。
隔离级别与锁的关系
- 在READ-UNCOMMITTED(读取未提交)隔离级别下,数据不会进行加锁。
- 在READ-COMMITTED(读取已提交)隔离级别下,会加共享锁,语句执行完之后就会释放锁。
- 在REPEATABLE-READ(可重复读),在读操作下会加共享锁,并且在事务结束之后才会进行释放。
- SERIALIZABLE(可串行化),会锁定整个范围的键,并且一直到事务结束。
锁粒度
在关系型数据库中,锁粒度一共有三种。
-
表级锁(table-level-locking) 表级锁是粒度最大的锁表方式,表示对当前操作的整张表进行加锁。锁资源消耗较少,MyIsAm和InnoDb都支持表级锁。
- 特点 开销小,加锁快。不会出现死锁,但是锁冲突率高,同时并发能力低。
-
行级锁(row-level-locking) 行级锁是颗粒度最小的锁表方式,它只会对当前操作的的记录进行锁定。行级锁,分为共享锁和排他锁。
- 特点 开销大,加锁慢。会出现死锁,锁冲突率低,并发能力高。
-
页级别锁 页级别锁,是表级别和行级别的一种折中方案。他会锁定当前操作的数据相邻的一组数据。
- 特点 开销和加锁时间介于行级和表级之间,会出现死锁,并发能力一般
共享锁与排他锁
- 共享锁:共享锁能同时存在多个,对数据加上共享锁之后,其他事务只能加共享锁对数据进行读取而不能进行修改。
- 排它锁 锁定的数据只能有一个排它锁,排他锁与其他类型的锁互斥,锁定的数据不能被其他操作进行读取或修改。
乐观锁和悲观锁
-
悲观锁: 假设数据冲突一定会发生,屏蔽掉一切可能违反数据完整性的操作,事务开启直接将数据锁死,直到事务完成。
-
乐观锁 :假设数据冲突一定不会发生,只在最后持久化之前对数据完整性进行检查,如果不一致取消操作。