数据库事务ACID特性,数据库四大隔离级别

2022-09-01 12:05:56

1.1事务的概念

1.1.1事物的概念

事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功。

//例如:a->b转账,对应如下两条sql语句
update account set money=money-100 where name= 'a';
update account set money=money+100 where name= 'b';

1.2管理事务

1.2.1数据库默认的事务

数据库默认支持事务的,但是数据库默认的事务是一条 sql 语句独占一个事务,这种模 式,意义不大.

1.2.2手动控制事务

如果希望自己控制事务也是可以的:

//开启事务,在这条语句之后的所有的 sql 将处在同一事务中,要么同时完成要么同时不完成
start transaction;
//事务中的 sql 在执行时,并没有真正修改数据库中的数据

//提交事务,将整个事务对数据库的影响一起发生
commit;

//回滚事务,将这个事务对数据库的影响取消掉
rollback;

1.3事务的ACID特性

1.3.1事务的四大特性

事务的四大特性是事务本身具有的特点。简称 ACID

  • 原子性(Atomicity)

 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发 生。

  • 一致性(Consistency)

事务前后数据的完整性必须保持一致。

  • 隔离性(Isolation)

事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务 所干扰,多个并发事务之间数据要相互隔离。

  • 持久性(Durability)

持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使 数据库发生故障也不应该对其有任何影响。

1.3.2隔离性可能造成的问题

数据库的其他三大特性数据库可以帮我们保证,而隔离性我们需要再讨论。

如果我们是数据库的设计者,该如何考虑设计数据库保证数据库的隔离性呢?

我们知道数据库的隔离性问题本质上就是多线程并发安全性问题。

可以用锁来解决多线成并发安全问题,但是如果用了锁,必然会造成程序的性能大大的 下降.对于数据库这种高并发要求的程序来说这是不可接受的.

我们可以具体分析下隔离性产生的细节:

如果两个线程并发修改,必然产生多线程并发安全问题,必须隔离开

如果两个线程并发查询,必然没有问题,不需要隔离

如果一个线程修改,一个线程查询,在不同的应用场景下有可能有问题,有可能没问题。

  • 脏读

一个事务读取到另一个事务未提交的数据

----------------------------
a 1000
b 1000
----------------------------
a:
start transaction;
update account set money=money-100 where name=a;
update account set money=money+100 where name=b;
-----------------------------
b:
start transaction;
select * from account;
a 900
b 1100
commit;
-----------------------------
a:
rollback;
-----------------------------
b:
start transaction;
select * from account;
a 1000
b 1000
commit;
  • 不可重复读

一个事务多次读取数据库中的同一条记录,多次查询的结果不同(一个事务读取到另一 个事务已经提交的数据)

------------------------------
a 1000 1000 1000
------------------------------
b:
start transaction;
select 活期 from account where name='a'; --- 活期存款:1000 元
select 定期 from account where name = 'a'; --- 定期存款:1000 元
select 固定 from account where name = 'a'; --- 固定资产:1000 元
---------------------------
a:
start transaction;
update account set 活期=活期-1000 where name= 'a';
commit;
---------------------------
select 活期+定期+固定 from account where name='a'; ---总资产:2000 元
  • 虚读(幻读)

有可能出现,有可能不出现:一个事务多次查询整表数据,多次查询时,由于有其他事务 增删数据, 造成的查询结果不同(一个事务读取到另一个事务已经提交的数据)

------------------------------
a 1000
b 2000
------------------------------
d:
start transaction;
select sum(money) from account; --- 总存款 3000 元
select count(*) from account; --- 总账户数 2 个
-----------------
c:
start transaction;
insert into account values ('c',3000);
commit;
-----------------
select avg(mone) from account; --- 平均每个账户:2000 元

1.3.3数据库四大隔离级别

Read uncommitted;

--- 不做任何隔离,可能造成脏读 不可重复度 虚读(幻读)问题

Read Committed;

-- 可以防止脏读,但是不能防止不可重复度 虚读(幻读)问题

Repeatable Read;

-- 可以防止脏读 不可重复度,但是不能防止 虚读(幻读)问题

Serializable;

-- 可以防止所有隔离性的问题,但是数据库就被设计为了串行化的数据库,性能很低

从安全性上考虑: Serializable > Repeatable Read > Read Committed > Read uncommitted

从性能上考虑: Read uncommitted > Read committed > Repeatable Read > Serializable

我们作为数据库的使用者,综合考虑安全性和性能,从四大隔离级别中选择一个在可以 防止想要防止的问题的隔离级别中性能最高的一个.

其中 Serializable 性能太低用的不多,Read uncommitted 安全性太低用的也不多, 我们通常从 Repeatable Read 和 Read committed 中选择一个.

如果需要防止不可重复读选择 Repeatable Read,如果不需要防止选择 Read committed

mysql 数据库默认的隔离级别就是 Repeatable Read

Oracle 数据库默认的隔离级别是 Read committed

  • 作者:别抢我辣条kiang
  • 原文链接:https://blog.csdn.net/weixin_52878530/article/details/123419688
    更新时间:2022-09-01 12:05:56