事务
引入案例
引入案例:张三丰向郭襄转500
张三丰 1000
郭襄 1000
语句1:update 表 SET 张三丰的余额=500 WHERE NAME='张三丰'
-- 语句1执行过程中出现了意外,则语句2也不应该继续执行
语句2:update 表 SET 郭襄的余额=1500 WHERE NAME='郭襄'
简介
事务:一个或一组sql语句组成一个执行单元,这个执行单元要么全部执行,要么全部不执行。
事务的属性(ACID)
- 原子性(Atomicity):一个事务不可再分割,要么都执行要么都不执行
- 一致性(Consistency):一个事务执行会使数据从一个一致状态切换到另外一个一致状态
例如:张三丰转账给郭襄,转账前后两个账户金额总数应保持不变 - 隔离性(Isolation):一个事务的执行不受其他事务的干扰
例如:事务T1和T2,对T1而言,T2要么在T1开始之前已经结束,要么在T1完成之后再开始执行 - 持久性(Durability):一个事务一旦提交,则会永久的改变数据库的数据.
事务的使用步骤 ★
分类
-
隐式(自动)事务:没有明显的开启和结束,本身就是一条事务可以自动提交,
比如insert、update、delete -
显式事务:事务具有明显的开启和结束的标记;
前提:必须先设置自动提交功能为禁用
语法
开启事务的语句;
update 表 set 张三丰的余额=500 where name='张三丰'
update 表 set 郭襄的余额=1500 where name='郭襄'
结束事务的语句;
具体步骤
#步骤1:开启事务
set autocommit=0;
start transaction;可选的
#步骤2:编写事务中的sql语句(select insert update delete)
语句1;
语句2;
...
#步骤3:结束事务
commit;提交事务
rollback;回滚事务
演示事务的使用步骤
-- 创建需要的表
SHOW VARIABLES LIKE 'autocommit';
SHOW ENGINES;
USE test;
DROP TABLE IF EXISTS accout;
CREATE TABLE account(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(20) NOT NULL,
balance DOUBLE
);
INSERT INTO account
VALUES(1, '张无忌', 1000),
(NULL, '赵敏', 1000);
SELECT * FROM account;
#1.演示事务的使用步骤
#①开启事务
SET autocommit=0;
START TRANSACTION;
#②编写一组事务的语句
UPDATE account SET balance = 500 WHERE username='张无忌';
UPDATE account SET balance = 1500 WHERE username='赵敏';
#③结束事务
#commit;
ROLLBACK;
事务中delete,truncate和savepoint的使用
演示事务对于delete和truncate的处理的区别
-- 使用delete
SET autocommit=0;
START TRANSACTION;
DELETE FROM account;
ROLLBACK; #可以回滚
-- 使用truncate
SET autocommit = 0;
START TRANSACTION;
TRUNCATE TABLE account;
ROLLBACK; #不能回滚
演示savepoint 的使用
SELECT * FROM account;
SET autocommit=0;
START TRANSACTION;
DELETE FROM account WHERE id=1;
SAVEPOINT a;#设置保存点 a是别名
DELETE FROM account WHERE id=2;
ROLLBACK TO a;#回滚到保存点,保存点之前的命令照样执行(删1不删2)
数据库的四种隔离级别
参考:数据库的4种隔离级别
并发问题
对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种并发问题:
- 脏读
对两个事务T1,T2。当T1正在修改数据,而这种数据 还没有提交到数据库中,这时,T2访问这个数据,然后使用了这个数据。之后, 若T2回滚, T1读取的内容就是临时且无效的。因为这个数据还没有提交那么另外一个事务读取到的这个数据我们称之为脏数据。 - 不可重复读
对于两个事务T1, T2。T1读取了一个字段, 然后T2 更新了该字段。之后, T1再次读取同一个字段, 值就不同了。 - 幻读
对于两个事务T1, T2。 T1 从一个表中读取了一个字段, 然后T2 在该表中 插入了一些新的行. 之后, 如果T1 再次读取同一个表, 就会多出几行。
四种隔离级别
脏读 | 不可重复读 | 幻读 | |
---|---|---|---|
READ UNCOMMITTED(读未提交) | × | × | × |
READ committed(读已提交) | √ | × | × |
REPEATABLE read(可重复读) | √ | √ | × |
serializable(串行化) | √ | √ | √ |
数据库的默认隔离级别与修改方式
Oracle 支持的2种事务隔离级别:READ COMMITED, SERIALIZABLE。
Oracle 默认的事务隔离级别为: READ COMMITED
Mysql 支持4种事务隔离级别.
Mysql 默认的事务隔离级别为: REPEATABLE READ
-- 查看当前会话隔离级别(MySQL8.0+)
select @@transaction_isolation;
-- 设置当前mySQL连接的隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL 隔离级别;
-- 设置数据库系统的全局的隔离级别:
set global transaction isolation level read committed;