TCL
/*
Trnsaction Control Language 事物控制语言
事物:
一个或一组sql语句组成一个执行单元,这个执行单元要么全部执行,要么全部不执行
事物的特性:
ACID
原子性:一个事物不可再分割,要么都执行,要么都不执行
一致性:一个事物执行会使数据从一个状态切换到另一个一致状态
隔离性:一个事物的执行不受其他事物的干扰
持久性:一个事物一旦提交,会永久改变数据库的数据
事物的创建
(1)隐式事物:事物没有明显的开启和结束标记(insert,update,delete语句等)
说明:自动提交功能默认是打开的
(2)显示事物:事物具有明显的开启和结束标记
前提:必须先设置自动提交功能为禁用
语法:
步骤1:开启事物
set autocommit=0;
start transaction;可选
步骤2:编写事物中的sql语句(select insert update delete)注意DDL语言中的create alter drop没有事物的概念
语句1;
语句2;
...
步骤3:结束事物
commit;提交事物
rollback;回滚事物
*/
#自动提交功能默认是打开的
SHOW VARIABLES LIKE 'autocommit';#ON
#关闭自动提交功能(仅仅对当前的事物生效,不是永久有效)
SET autocommit=0;
#自动提交功能已经关闭
SHOW VARIABLES LIKE 'autocommit';#OFF
DROP TABLE IF EXISTS account;
CREATE TABLE account(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(20),
balance DOUBLE
);
INSERT INTO account(username,balance)
VALUES('张无忌',1000),('赵敏',1000);
#演示显示事物的使用步骤
#开启事物
SET autocommit=0;
START TRANSACTION;
#编写一组事物的语句
UPDATE account SET balance=500 WHERE username='张无忌';
UPDATE account SET balance=1500 WHERE username='赵敏';
#结束事物1
COMMIT;
SELECT * FROM account;#500 1500
#开启事物
SET autocommit=0;
START TRANSACTION;
#编写一组事物的语句
UPDATE account SET balance=1000 WHERE username='张无忌';
UPDATE account SET balance=1000 WHERE username='赵敏';
#结束事物2
ROLLBACK;
SELECT * FROM account;#500 1500
#2.介绍delete和truncate在事物中的区别
#delete可以成功回滚
SET autocommit=0;
START TRANSACTION;
DELETE FROM account;
ROLLBACK;
SELECT * FROM account;#记录还有
#truncate
SET autocommit=0;
START TRANSACTION;
TRUNCATE TABLE account;
ROLLBACK;
SELECT * FROM account;#没有记录了
/*
【问题】
同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致一下各种并发问题:
脏读: 对于两个事务 T1, T2, T1 读取了已经被 T2 更新但还【没有被提交】的字段. 之后, 若 T2 【回滚】, T1读取的内容就是临时且无效的.
不可重复读: 同一个事务中,多次读取到的数据【不一致】
幻读: 一个事务读取数据时,另外一个事务进行【更新(一般是插入和删除)】,导致第一个事务读取到了没有更新的数据
【避免】
通过设置事务的隔离级别(由低到高)
1、READ UNCOMMITTED隔离级别最低,啥都避免不了避免
2、READ COMMITTED 可以避免脏读
3、REPEATABLE READ(默认) 可以避免脏读、不可重复读和一部分幻读
4、SERIALIZABLE可以避免脏读、不可重复读和幻读
*/
尝试READ UNCOMMITTED隔离级别(左图为第一个事物,右图为第二个事物):
尝试READ COMMITTED隔离级别(左图为第一个事物,右图为第二个事物):
尝试REPEATABLE READ隔离级别(左图为第一个事物,右图为第二个事物):
尝试SERIALIZABLE隔离级别(左图为第一个事物,右图为第二个事物):
/*
savepoint 设置保存点
仅仅搭配rollback使用
*/
SET autocommit=0;
START TRANSACTION;
DELETE FROM account WHERE id=1;
SAVEPOINT a;#设置保存点
DELETE FROM account WHERE id=2;
ROLLBACK TO a;#回滚到保存点处,也就是删除第一行,不删除第二行
SELECT * FROM account;