数据库中的事务 - Go语言中文社区

数据库中的事务


一.事务(transaction)

定义:事务就是一个对数据库操作的序列,是一个不可分割的工作单位,要不这个序列里面的操作全部执行,要不全部不执行。
特性:原子性 (Atomicity) 持久性(Durability) 一致性(Consistency) 隔离性(Isolation)
下面我将用银行转账来举例说明事务的ACID特性

//创建数据库
create table bank
(
    id int primary key not null,
    name varchar(50),
    money decimal
);
//两个用户注册账号存钱
 insert into bank(id,name,money) value(1,'小胖',1000);
 insert into bank(id,name,money) value(2,'小胖的爸爸冯天浩',1000);

二.原子性

事务的原子性是指一个事务是一个不可分割的工作单位,要不全部执行,要不全部不执行。

1.举例

这里写图片描述

begin;
update bank set money=money-100 where name='小胖的爸爸冯天浩';
update bank set money=money+100 where name='小胖';
commit;

2.可能出现的问题

在生活中如果出现了一些意外情况,例如小胖的爸爸冯天浩给小胖转了100,但是由于突然断电,小胖却没收到钱,小胖的爸爸的钱却已经少了,这样会产生纠纷。本质就是只执行了扣款语句,却没有执行加款语句。

3.解决措施

数据库管理系统为了保证事务的原子性对一个事务的执行时,会采取两种措施,全部执行和全部不执行,这样上述问题的结果就会变成两种:小胖的爸爸冯天浩的money减少了100,小胖的money增加100或者小胖的爸爸没有减少钱,小胖也没增加钱。

三.一致性

一致性是指在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。这是说数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。
在这简单说一下约束,刚才我们说保持一致性就是不能破坏数据库的约束,那么什么是数据库的约束呐?简而言之约束就是一些限制条件,限制你可以做什么不可以做什么。

1.举例

对于上述银行转账来说,无论转钱是否成功,都必须要保证bank中money总数为2000。

2.解决措施

为了保证事务的一致性,从数据库层面来看,在一个事务执行的前后数据会符合我们之前设置的约束(唯一约束,外键约束,Check约束等)和触发器设置。这一点是由SQL SERVER进行保证的。比如转账,则可以使用CHECK约束两个账户之和等于2000来达到一致性目的。

四.持久性

持久性即当一个事提交后,对数据库的改变是永久性的,不会被回滚。
sql service 通过write ahead transaction log 来保证事务的持久性,write ahead transaction log即在事务对数据库的改变写入数据库之前首先写入事务日志文件,而事务日志文件将按顺序排序。当数据库发生意外情况后,重启sql service后首先会对事务事务日志顺序号进行检查,将本应该对数据库做改变却未做的部分持久化到数据库,来保证事务的持久性。

五.隔离性

事务隔离性是指多个事务并发执行时,相互之间无影响。
主要是在,多用户,多并发的情况下,多个事务对同一个数据进行访问时,只能看到这个数据在上一个事务修改前的状态或者修改后的状态,不会看到中间状态的数据。

1.事务之间相互影响的种类

脏读 不可重复读 幻读 丢失更新

1.1脏读

脏读:一个事务读取了另一个事务未提交的数据,如下图,此时小胖是受损的。
这里写图片描述

1.2不可重复读

就是在一个事务范围内,两次相同的查询会返回两个不同的数据,是因为在此间隔内有其他事务对数据进行了修改。如下图:
这里写图片描述

1.3幻读

幻读,是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样.
如下图:
这里写图片描述

1.4丢失更新

两个事务同时读取同一条记录,A先修改记录,B也修改记录(B是不知道A修改过),B提交数据后B的修改结果覆盖了A的修改结果。

2.sql server 中的数据库的事务隔离级别

数据库的事务隔离级别(TRANSACTION ISOLATION LEVEL)是为了尽可能的避免上述事务之间的影响而产生的隔离级别。
这里写图片描述
sql server 隔离事务之间的影响是通过锁来实现的,通过阻塞来隔离上述影响,级别越高,加的锁越多,效率越地下。
未提交读:在读取数据时不会加任何锁,也不会进行检测,可能会读到没有提交的数据。
已提交读:只读取提交的数据等待其他事物释放排他锁,读数据的共享锁在读操作完成后会立即释放。这个隔离级别是sql server默认的隔离级别。
可重复读:像已提交读一样,但共享锁会保持到事物结束才会释放。
可串行读:类似于可重复读,但锁不仅会锁定所查询的数据,也会锁定所查询的范围,这样就阻止了新数据插入所查询的范围。

七.总结

事务的(ACID)特性是由关系数据库管理系统(RDBMS,数据库系统)来实现的。数据库管理系统采用日志来保证事务的原子性、一致性和持久性。日志记录了事务对数据库所做的更新,如果某个事务在执行过程中发生错误,就可以根据日志,撤销事务对数据库已做的更新,使数据库退回到执行事务前的初始状态。

  数据库管理系统采用锁机制来实现事务的隔离性。当多个事务同时更新数据库中相同的数据时,只允许持有锁的事务能更新该数据,其他事务必须等待,直到前一个事务释放了锁,其他事务才有机会更新该数据。

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_37447414/article/details/81432675
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-07 15:14:38
  • 阅读 ( 690 )
  • 分类:数据库

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢