事务介绍
概念
- 事务通常指访问并可能更新数据库中各种数据项的一个程序执行单元(unit),if一个包含多个步骤的业务操作,被事务管理,那么这些操作要么同时成功,要么同时失败。
为什么需要事务?
- 事务的引入通常是为了解决数据库业务操作的一致性,防止业务操作出现混乱。
事务的操作
- 开启事务 start transaction
回滚roll back
提交commit
案例
实现张三给李四转账的案例,在数据库表执行如下的sql。
CREATE TABLE account (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10),
balance DOUBLE
);
INSERT INTO account (NAME,balance) VALUES ('zhangsan',1000),('lisi',1000);
转账sql代码
-- 确保每张三和李四的账户余额都是1000块;
UPDATE account SET balance = 1000;
-- 开启事务
START TRANSACTION;
UPDATE account SET balance=balance-500 WHERE NAME='zhangsan';
UPDATE account SET balance=balance+500 WHERE NAME='lisi';
-- 事务没有问题 提交事务
COMMIT;
-- 事务出现问题,则回滚事务
ROLLBACK;
转账成功
转账失败,事务回滚到初始状态。
mysql的事务操作
在mysql中DML (增删改)语句一般默认自动提交; ORACLE 数据库是手动提交的
事务提交方式
自动提交
- mysql就是自动提交事物的,一条DML(增删改)语句会提交一次事务。
手动提交
- 需要先开启事务,再提交事务
修改事务的提交方式
- 查看事务的提交方式。
SELECT @@autocommit;
notes:如果值为1表示自动提交(mysql的默认值),如果值为0表示。
2. 修改事务的默认提交方式
事务的特征
原子性
- 事务的原子性是指不可分割的最小操作单位,要么同时成功,要么同时失败。
持久性
- 当事务提交或回滚后,数据库会持久化的保存数据。
隔离性
- 多个事务之间,相互独立。
一致性
- 事务操作前后,总量保持不变。
对于一致性和原子性的理解
- 原子性关注状态,要么全部成功,要么全部失败,不存在部分成功的状态。
- 而一致性关注数据的可见性,中间状态的数据对外部不可见,只有最初状态和最终状态的数据对外可见。
事务的隔离级别
什么是事务的隔离级别?
- 多个事务之间隔离的,相互独立的。但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题。
事务隔离级别存在的问题
脏读
脏读一般指的一个事务读取到另一个事务未提交的事务。
不可重复读
- 不可重复读(虚读):在同一个事务中,两次读取的数据不一样。例如:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致。(B事务不断进行修改操作)
幻读
- A事务操作(DML)数据表中所有记录,B事务添加或删除了一条数据,则第一个事务查询不到自己的修改的结果。(B事务进行了增删操作)
隔离级别(产生的原因及解决方法)
read uncommitted
- 读未提交的事务,产生脏读,可重复度、幻读。
read committed
- 解决的问题: 防止了脏读。
产生的问题:没有解决可重复度、幻读的问题。
repeatable read
- 解决的问题:解决了脏读、可重复读的问题
未解决问题: 幻读任然没有解决
serializable
- 解决的问题: 可以解决所有问题。
注意的问题
随着隔离级别的提高安全性也会越来越高,然效率会降低。
mysql默认的隔离级别是repeatable read
oracle默认的事务隔离级别是 read committed
数据库事务隔离级别操作
查询事务隔离级别
select @@tx_isolation;
设置事务隔离级别
-- 级别字符串
-- read uncommitted
-- read committed
-- repeatable read
-- serializable
set global transaction isolation level 级别字符串;
- notes:注意在设置完毕后重新建立连接方能生效。
案例
查看事务未提交的所引发的脏读问题:
扫描二维码关注公众号,回复:
12321114 查看本文章
SET GLOBAL TRANSACTION ISOLATION LEVEL read uncommitted;
关闭原来的窗口,重新启动cmd执行下面的语句
select @@tx_isolation;
修改隔离级别完成。
初始状态:
开始转账操作
start transaction;
-- 转账操作
update account set balance = balance - 500 where id = 1;
update account set balance = balance + 500 where id = 2;
将事务隔离级别设置成读已提交并重新设置账户余额。
set global transaction isolation level read committed;
UPDATE account SET balance = 1000;
上述案例的主要问题在于事务B在开启事务后,即同一事务中所读取的数据不一致,不一致问题主要体现于步骤6、8、11中。
set global transaction isolation level repeatable read;
UPDATE account SET balance = 1000;
从上图中可得知,A事务在转账操作后保持一致,具体体现在步骤5、7、9上,而事务B也是在事务A提交之前数据保持稳定,具体体现在步骤6、8、11,12解决了可重复读的问题。
至此,mysql中有关事务的知识复习到此了。