数据库事务简介

Posted java全栈技术

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据库事务简介相关的知识,希望对你有一定的参考价值。

1.数据库事务简介

1.1  事务的ACID特性:

  • A:Atomicity 原子性:事务必须 是一个不可分割的整体 , 要么全部执行,要么全部不执行。

  • C:Consistency:一致性 也就是说执行完数据库操作后,数据不会被破坏。比如:如果从A账户转账到B账户,不可能以为A账户扣了钱,B账户没有加钱。

  • I:Isolation 隔离性 比如我们编写了一条update语句,提交到数据库的一刹那,有可能别人也提交了一条delete语句到数据库中。也许我们都是对同一条记录进行操作,如果不加控制,就会出大麻烦。

  • D:Durability 持久性 如果执行一条insert语句后,数据库必须保证有一条永地存放 在磁盘中

原子性是基础,隔离性是手段,持久性是目睹,真正的老大 是一致性。

事务所面临的问题:

ACID 这4条特征当中,其实最难理解的不是一致性,而是隔离性。事务 隔离级别是为了解决数据在高并发下产生的问题:

  • Dirty Read (脏读)

  • Unrepeatable Read(不可重复读)

  • Phantom Read(幻读)

脏读:

时间 事务A(存款) 事务B(取款)
T1 开始事务 ---
T2 --- 开始事务
T3 --- 查询余额(1000元)
T4 --- 取出1000元(余额为0)
T5 查询余额(0 元) ---
T6 --- 撤销事务(余额恢复为1000元)
T7 存入500元(余额 500) ---
T8 提交事务 ---

余额应该为1500元才对。请看T5时间点,事务A此时查询余额为0,这个数据就是脏数据,它是事务B造成的,明显事务没有进行隔离。

不可重复读

时间 事务A(存款) 事务B(取款)
T1 开始事务 ---
T2 --- 开始事务
T3 --- 查询余额(1000元)
T4 查询余额(1000) ---
T5 --- 取出1000元(余额为0)
T6 --- 提交事务
T7 查询余额(0元) ---

事务A除了查询了两次意外,其他什么事情都没有做,结果钱从1000变为0了,这就是重复读了,其实这样也是合理地,毕竟事务B提交了事务,数据库将结果进行了持久化,所以事务A再次读取时自然发生了变化。

这种现象基本上市可以理解的,但是在“变态”的场景下缺是不允许的。毕竟这种现象也是事物之间没有隔离造成的,但是我们对于这种问题似乎可以忽略。

幻读

时间 统计总存款 事务B(存款)
T1 开始事务 ---
T2 --- 开始事务
T3 统计总存款(10000元) ---
T4 --- 存入100元
T5 --- 提交事务
T6 统计 总存款(101000元) ---

归纳一下,以上提到了事务并发所引起的与读取数据有关的问题,各用一句话来描述:

  • 脏读----事务A读取了事务B未提交的数据,并在这个基础 上又做了其他操作

  • 不可重复读--- 事务A读取了事务B已提交的数据

  • 幻读--- 事务A读取 了事务B已提交的新增数据

第一条是坚决抵制的,后两条在大多数情况下可以不考虑

不同的事务隔离级别能处理的事务并发问题如下表:

事务隔离级别 脏读 不可重复读 幻读
READ_UNCOMMITED 允许 允许 允许
READ_COMMITED 禁止 允许 允许
REPEATABLE_READ 禁止 禁止 允许
SERIALIZABLE 禁止 禁止 禁止

JDBC也提供了这四类事务隔离级别,但默认事务隔离级别对不同的数据库产品而言却是不一样的。mysql默认的事务隔离级别是READ_COMMITTED,READ_COMMITTED 已经可以解决绝大多数问题了,其他的就具体问题具体分析了。

可以使用下面代码来获取使用的数据库的隔离 级别:

1DatabaseMetaData meta = DBUtil.getDataSource().getConnection();
2getMetaData();
3int defaultIdolation = meta.getDefaultTransactionIsolation();

数据库是怎样实现隔离级别的呢?其实就是“锁”,当插入数据时,就是锁表;当更新数据时,就锁定行,这叫锁行。


以上是关于数据库事务简介的主要内容,如果未能解决你的问题,请参考以下文章

如何绕过将数据模型传递给片段参数以避免事务太大异常?

回栈事务后如何持久化分片数据?

片段事务分离和附加后ListView不工作?

理解片段事务期间片段的生命周期方法调用

提交带有全屏片段的片段事务

使用 OnItemClickListener 列出视图片段到片段事务