本文的思维导图如下:
图片说明
图片说明
1.事务的概念
事务由单独单元的一个或多个SQL语句组成,在这个单元中,每个SQL语句是相互依赖的。而整个单独单元作为一个不可分割的整体,如果单元中某条SQL语句一旦执行失败或产生错误,整个单元将会回滚。所有受到影响的数据将返回到事物开始以前的状态;如果单元中的所有SQL语句均执行成功,则事物被顺利执行。
2.事务的特性:ACID
1)原子性(Atomicity)
原子是物理中最小的单元,不能再细分。原子性是指事务是一个不可分割的工作单位,事务中的操作要么
都发生,要么都不发生。
2)一致性(Consistency)
事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
3)隔离性(Isolation)
事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
4) 持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。
3.事务的操作步骤
1)开启事务:set autocommit=0;
2)编写事务中的SQL语句,可以是一条或多条;
3)结束事务或回滚;commit;/rollback;(结束事务则前面的SQL语句会被执行,回滚则都不会被执行)。
4.事务操作的实例代码
基础工作:首先新建一张表,代码见文末,效果如下。
图片说明
1)第一步:开启事务,代码如下:
set autocommit=0;
start transaction;(该语句可以写也可以不写)
事务开关
2)编写一组事务的语句
#业务场景:zhang向pan转账了500元,之后更新两个人现有的钱,语句如下:
update salary set money=500 where name="zhang";
update salary set money=1500 where name="pan";
3)结束事务
commit;结果如下:
图片说明
5.数据库的隔离级别
对于多个并发的事务,当它们访问相同的数据时,如果缺乏必要的隔离机制,将会导致如下的并发问题:
脏读: 对于两个事务 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段。之后, 若T2回滚, T1读取的内容就是临时且无效的。
不可重复读: 对于两个事务T1, T2, T1 读取了一个字段, 然后T2 更新了该字段。之后, T1再次读取同一个字段, 值就不同了。
幻读: 对于两个事务T1, T2, T1 从一个表中读取了一个字段, 然后T2 在该表中插入了一些新的行。之后,如果T1再次读取同一个表, 就会多出几行。
数据库事务的隔离性: 数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响, 避免各种并发问题。
一个事务与其他事务隔离的程度称为隔离级别。数据库规定了多种事务隔离级别, 不同隔离级别对应不同的干扰程度, 隔离级别越高, 数据一致性就越好, 但并发性越弱。
数据库提供的4种隔离级别及描述如下:
四级的隔离级别
不同的隔离级别是否会出现不同的并发问题,如下表:
图片说明
数据库产品中,Oracle支持2 种事务隔离级别:READ COMMITED,SERIALIZABLE。Oracle 默认的事务隔离级别为: READ COMMITED;Mysql支持4 种事务隔离级别,默认的事务隔离级别: REPEATABLE READ。
6.数据库的隔离级别的实例代码
每启动一个 mysql 程序, 就会获得一个单独的数据库连接. 每个数据库连接都有一个全局变量 @@transaction_isolation, 表示当前的事务隔离级别。
1)查看当前的隔离级别: select @@transaction_isolation;(老版本sql用select @@tx_isolation)。实例如下:
图片说明
2)设置当前的隔离级别:set session transaction isolation level 隔离级别名;
3)两个并发的事务
首先打开两个cmd,将当前的隔离都调整到最低级别read uncommitted,之后开启两个事务。
图片说明
先开启第一个事务,之后更新数据,完成pan向zhang转账500元:
set autocommit=0;
update salary set money=1000 where name="zhang";
update salary set money=1000 where name="pan";
此时不结束事务1,而是开启事务2,在事务2中读取数据:
图片说明
读到了更新之后的数据,但之后事务1回滚,事务2再读取数据时,数据就不同了,第一次读到的数据,我们就称为脏读。
图片说明
另外的两种问题:不可重复读和幻读的操作类似,这里仅放截图的代码:
图片说明

图片说明
代码:
#首先做下基础的工作,使用数据库,并新建一张工资表
use mysql;
create table salary(id int primary key,name varchar(20),money int);
#之后插入数据
insert into salary(id,name,money) values(1,"zhang",1000);
insert into salary(id,name,money) values(2,"pan",1000);
insert into salary(id,name,money) values(3,"zhou",1000);
#小技巧:姓名那列要显示中文字符时,使用set name gbk;

写作不易,开源不易,如果您觉得本篇博文对您有帮助的话,欢迎微信打赏,您的支持是我写作的动力:
图片说明