博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数据库事务的四大特性
阅读量:4960 次
发布时间:2019-06-12

本文共 2236 字,大约阅读时间需要 7 分钟。

一个设计良好的数据库可以帮我们保证事务具有四大特性(ACID):

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

一致性:如果事务执行之前数据库是一个完整的状态,那么事务结束后,无论事务是否执行成功,数据库仍然是一个完整的状态。

  数据库的完整状态:当一个数据库中的所有的数据都符合数据库中所定义的所有约束,此时可以称数据库是一个完整的状态。

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

持久性:指一个事务一旦被提交,他对数据库的影响是永久性的。

 

数据库可以保证原子性,一致性,持久性。但是隔离级别需要根据并发情况进行设置,

将数据库设计成单线程,可以防止所有的线程安全问题,自然也就保证了隔离型的问题,但是如果这样,那么效率就会极其低下。

如果两个线程并发修改,一定会相互捣乱,这时必须利用锁机制防止多个线程的并发修改

如果两个线程并发查询,没有线程安全问题。

如果两个线程一个修改,一个查询:

  四大隔离级别:

  Read uncommitted:---不防止任何隔离型问题,不能防止脏读/不可重复读/幻读问题。

  Read commit:---可以防止脏读问题,但是不能防止 不可重复读/幻读问题。(oracle默认隔离级别)

  Repeatable read:---可以防止脏读/不可重复读,不能防止幻读。(mysql默认隔离级别)

  Serializable:--数据库被设计为单线程,可以防止上述所有问题

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

  场景:a账户1000,b账户1000,a到b的网店里买一百块钱的鞋子。。。。

  a:start transaction

  update table set money=money-100 where name='a';//a账户扣除100

  update table set money=money+100 where name='b';//b账户增加100

  此时a还没有提交事务,对b说付款成功

  b:start transaction;//b开始查询自己的账户余额

  select money form table where name='b';

  b:commit;

  如果读取到了a没有提交的数据,那么b查出来的就会是1100,此时b开始发货

  此时a执行回滚

  a:rollback;

  那么b再去查询账户余额会发现自己的账户还是原先的100块

 

  不可重复读:在当前事务中,读取到了另一事务提交的更新和删除的数据。

  场景:如果a有活期资金1000,定期1000,固定资产1000

  a: 1000 1000 1000

  b: 银行职员,银行让职员b算出a客户的总共资产
  ---------
  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客户取走了自己活期的1000元
    a:
    start transaction;
    update accounset set 活期=活期-1000 where name='a';
    commit;
  -------
  select 活期+定期+固定 from account where name='a'; --- 总资产:2000,按照之前查出来的应该是3000元,但是现在是2000元
  commit;
  ----------

  但是虽然在这种场景下,出现了不可重复读,但是如果在另一场景下,如果你和你的伙伴共用一个银行账户共100万,你的伙伴如果中途取走了50万,而你此时读取到剩下的50万,就符合该场景。

  幻读:在当前事务中,读取到了另一事务提交的插入的数据

  场景:如果银行现在有a、b两位客户存款各1000,银行老板让职员b去算平均每个客户的平均存款,而又有新增客户c存入了4000元。

  a: 1000

  b: 1000
  d: 银行业务人员
  -----------
  d:
  start transaction;
  select sum(money) from account; --- 2000 元
  select count(name) from account; --- 2 个
  ------
  c:
start transaction;
insert into account values(c,4000);
commit;
------
select sum(money)/count(name) from account; --- 平均:2000元/个,结果应该是平均存款1000,而实际结果确实2000
commit;

------

转载于:https://www.cnblogs.com/lpbk/p/11433174.html

你可能感兴趣的文章
MYSQL乱码问题。
查看>>
LINQ之路 9:LINQ to SQL 和 Entity Framework(上)
查看>>
c语言链表实现一元多项式的加减乘运算
查看>>
"Accepted today?"
查看>>
英语学习之‘加减乘除’
查看>>
codevs 2800 送外卖 TSP问题
查看>>
子查询:相关子查询、无关子查询
查看>>
小型开发团队的测试误区
查看>>
004-数据类型(String)
查看>>
最简单实现一个数据库
查看>>
php备份数据库
查看>>
Java 编程入门(词汇表)
查看>>
基于jquery的js幻灯片类
查看>>
tap事件的原理详解
查看>>
申请Let's Encrypt永久免费SSL证书
查看>>
Windows XP硬盘安装Windows7
查看>>
机房收费系统测试
查看>>
数组,集合分割函数,join()
查看>>
JWT
查看>>
2019西北工业大学程序设计创新实践基地春季选拔赛 I Chino with Rewrite (并查集+树链剖分+线段树)...
查看>>