1. 事务的概念
- 一条或多条 SQL 语句组成一个执行单元,其特点是这个单元要么同时成功要么同时失败
- 单元中的每条 SQL 语句都相互依赖,形成一个整体
- 如果某条 SQL 语句执行失败或者出现错误,那么整个单元就会回滚,撤回到事务最初的状态
- 如果单元中所有的 SQL 语句都执行成功,则事务就顺利执行
2. 事务的基本使用
-- 创建db_transaction数据库
CREATE DATABASE db_transaction;
-- 使用db_transaction数据库
USE db_transaction;
-- 创建账户表
CREATE TABLE account(
id INT PRIMARY KEY AUTO_INCREMENT, -- 账户id
NAME VARCHAR(20), -- 账户名称
money DOUBLE -- 账户余额
);
-- 添加数据
INSERT INTO account VALUES (NULL,'张三',1000),(NULL,'李四',1000);
-- 张三给李四转账500元
-- 开启事务
START TRANSACTION;
-- 1.张三账户-500
UPDATE account SET money=money-500 WHERE NAME='张三';
出错了...
-- 2.李四账户+500
UPDATE account SET money=money+500 WHERE NAME='李四';
-- 结束事务
-- 回滚事务
ROLLBACK;
-- 提交事务
COMMIT;
3. 事务的提交方式
/*
查询事务提交方式:SELECT @@AUTOCOMMIT; -- 1代表自动提交 0代表手动提交
修改事务提交方式:SET @@AUTOCOMMIT=数字;
*/
-- 查询事务的提交方式
SELECT @@autocommit;
-- 修改为手动提交
SET @@autocommit = 0;
UPDATE account SET money=2000 WHERE id=1;
-- 操作数据后需要手动提交,不然不会永久存储
COMMIT;
-- 修改事务的提交方式
SET @@autocommit = 1;
4. 事务的四大特征
原子性(atomicity):
原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响
一致性(consistency):
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态
拿转账来说,假设张三和李四两者的钱加起来一共是2000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是2000,这就是事务的一致性
隔离性(isolcation):
隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离
持久性(durability):
持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作
5. 事务的隔离级别
1 | 读未提交 | read uncommitted |
---|---|---|
2 | 读已提交 | read committed |
3 | 可重复读 | repeatable read |
4 | 串行化 | serializable |
- 读未提交:产生脏读、不可重复读、幻读问题
- 读以提交:解决脏读问题
- 可重复读:解决脏读、不可重复读问题
- 串行化:解决幻读、脏读、不可重复读问题
问题 | 现象 |
---|---|
脏读 | 是指在一个事务处理过程中读取了另一个未提交的事务中的数据 , 回滚导致两次查询结果不一致 |
不可重复读 | 是指在一个事务处理过程中读取了另一个事务中修改并已提交的数据, 提交导致两次查询结果不一致 |
幻读 | select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入。或不存在执行delete删除,却发现删除成功 |
查询和修改事务的级别:
/*
查询隔离级别:SELECT @@TX_ISOLATION;
修改隔离级别:SET GLOBAL TRANSACTION ISOLATION LEVEL 级别字符串;
*/
-- 查询事务隔离级别
SELECT @@tx_isolation;
-- 修改事务隔离级别(修改后需要重新连接)
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
read uncommitted等级:
脏读问题:事务A修改了数据但是并未提交,此时事务B查看数据为修改的状态,如果事务A执行回滚操作,此时事务B再次查看数据会得到不同的结果。
read committed等级:
可以解决脏读问题:事务A修改数据但是未提交,此时事务B中查看到的是修改前的数据,只有事务A提交后,事务B才能查看到修改后的数据。
不可重复读问题:事务A修改数据后但未提交,此时事务B查看到的是修改前的数据,在事务A提交后,此时事务B查看到的是修改后的数据,也会造成两次查看数据不同。
repeatable read等级:
可以解决不可重复读问题:事务A在修改数据后未提交,事务B查看到的是修改前的数据,事务A在提交之后,事务B查看到的仍然是修改前的数据,只有事务B在提交只有才能看到修改后的数据。
幻读问题:事务A向表添加了一条数据没有提交,事务B此时添加不了数据(转圈),在事务A提交后事务B的添加语句报错添加不了数据,但是在事务B提交事务后,查看表发现数据已经添加成功,就好像产生幻觉。
serializable等级:
可以解决幻读问题:在serializable等级下的事务相当于一个锁表操作,在事务A没有提交事务之前,其他事务不能做任何操作,查询也不可以
隔离级别总结:
隔离级别 | 名称 | 出现脏读 | 出现不可重复读 | 出现幻读 | 数据库默认隔离级别 | |
---|---|---|---|---|---|---|
1 | read uncommitted | 读未提交 | 是 | 是 | 是 | |
2 | read committed | 读已提交 | 否 | 是 | 是 | Oracle / SQL Server |
3 | repeatable read | 可重复读 | 否 | 否 | 是 | MySQL |
4 | serializable | 串行化 | 否 | 否 | 否 |
如有错误欢迎留言评论,2021年7月14日 羽露风