数据库事务
1.数据库的特性
- 原子性 Atomic
- 一致性 Consistency
- 隔离性 Isolation
- 持久性 Durability
特性 | 说明 |
---|---|
原子性 Atomic | 一次事务的多个数据库操作是不可分割的原子单元,所有操作要么成功,要么失败,不会有第三种状态 |
一致性 Consistency | 一个事务或者多个事务的操作后,数据库所处的状态和业务规则是一致的;简单来说,两者互相转账,数据总和是不变的 |
隔离性 Isolation | 每个事务的业务操作都是隔离的原则是不会互相影响,但是和你数据库隔离性的设置有关,隔离性越高,并发性越低,反之相反。 |
持久性 Durability | 一旦事务提交成功,事务中的数据必须持久化到数据库;即使数据库宕机,也可以通过操作日志来恢复数据 |
- 这四个特性中,核心是:一致性。其他都是围绕数据的一致性采取的措施
2.并发存在的问题
在数据库中,同样数据有可能被多个事务访问。假如没有采取必要的措施,就会导致各种问题,从而破坏数据的完整性
- MySQL采用数据库锁来保证事务的隔离性,当多个事务对同一份数据进行操作时,只有持有数据库锁的事务才可以真正地操作数据
- Oracle采用数据库版本机制来隔离事务,在回滚阶段为每个事务操作保留一个版本,这样每个事务就修改自己的版本数据,不会影响到其他事务
2.1三类数据读取问题
- 脏读 dirty read
- 不可重复读 unrepeatable read
- 幻读 phantom read
-
脏读 dirty read
A事务读取到B事务更改的数据,此时B事务回滚了,那么A事务拿到B事务回滚之前的数据去做业务操作是可怕的
-
不可重复读 unrepeatable read
一个事务在不同的时间点读取同一条数据是不一样的:比如说事务A更改a=100,事务B读到a=100,之后事务A更改a=90,事务B再次读就是a=90了
-
幻读 phantom read
幻读一般发生在统计事务中:事务A统计一张表的数据,这时事务B新增一条记录,事务A发现再次统计就发现不一样了,这就发生了幻读
-
幻读和不可重复读的区别
比较 | 不可重复读 | 幻读 |
---|---|---|
场景 | 一个事务读取另一个事务修改或者删除的数据 | 一个事务读取到另一个事务的新增的数据 |
解决 | 对所操作的数据加行级锁,避免操作的数据发生变化 | 对操作的数据加表级锁,锁定整张表 |
2.2两类数据更新问题
- 第一类丢失更新
- 第二类丢失更新
-
第一类丢失更新
A事务
回滚时,直接把B事务的提交更新的数据给覆盖了:事务A,B都查询a=100,此时A修改a+10=110,B修改a+10=110,A不管B已经提交事务,进行回滚,修改a=100,那B事务哭了,我加的10不见了
-
第二类丢失更新
A事务
提交了并且覆盖了B事务的数据,导致B事务的丢失
数据库设置的隔离等级和会发生的并发问题
数据库设置的隔离级别 | 数据一致性等级 | 脏读 | 不可重复读 | 幻读 | 第一类丢失更新 | 第二类丢失更新 |
---|---|---|---|---|---|---|
未提交读(Read uncommitted) | 最低级别 | 发生 | 发生 | 发生 | 避免 | 发生 |
已提交读(Read committed) | 语句级 | 避免 | 发生 | 发生 | 避免 | 发生 |
可重复读(Repeatable read) | 事务级 | 避免 | 避免 | 发生 | 避免 | 避免 |
可序列化(Serializable) | 最高等级 | 避免 | 避免 | 避免 | 避免 | 避免 |
- 数据库的并发性和事务隔离等级是相反的,隔离等级低,并发性好,反之相反
数据库中的锁
为啥要锁?
-
数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则--->简单来说并发会出现数据不一致问题
mysql举例
-
对于任何一种数据库来说都需要有相应的锁定机制,所以MySQL自然也不能例外
-
MySQL数据库由于其自身架构的特点,存在多种数据存储引擎,每种存储引擎所针对的应用场景特点都不太一样,为了满足各自特定应用场景的需求,每种存储引擎的锁定机制都是为各自所面对的特定场景而优化设计,所以各存储引擎的锁定机制也有较大区别。
Mysql有哪些锁呢?
锁类型 | 适用引擎 | 锁颗粒度 | 系统开销 | 加锁速度 | 发生冲突的概率 | 是否出现死锁 | 并发度 |
---|---|---|---|---|---|---|---|
表级锁 table-level | MyISAM,MEMORY,CSV等,非事务性存储引擎 | 大(锁定整张表) | 小 | 快 | 高 | 不会 | 低 |
页级锁 page-level | BerkeleyDB存储引擎 | 小 | 大 | 慢 | 低 | 会 | 高 |
行级锁 row-level | InnoDB存储引擎 | 最小 | 大 | 最慢 | 最低 | 会 | 最高 |
-
表级锁 table-level
作为颗粒度最大的锁机制,该锁实现的机制非常简单,所以系统开销小,加锁和释放锁比较快完成。由于锁定整张表,有效的避免死锁问题
-
页级锁 page-level
他是mysql独特的锁,它是介于表级锁和行级锁之间的,所以它的所需要的系统开销和并发等都是在两者之间的
-
行级锁 row-level
作为颗粒度最小锁,所以发生锁争夺的概率非常小,并发性能高,但是加锁和解锁的资源消耗比较大,由此发生死锁的概率比较高
关于数据库锁,这位大佬介绍的非常详细数据库的锁