#TCL
/*
Transaction Control Language 事务控制语言
事务:
一个或一组sql语句组成一个执行单元,这个执行单元要么全部执行,要么全部不执行。
案例:转账
zhang3 1000
li41000
update 表1 set zhang3的余额=500 where name='zhang3'
-- 此时出现问题
update 表2 set li4的余额=1500 where name='li4'
*/
/*
事务的创建:
隐式事务:事务没有明显的开启和结束的标记.
比如insert、update、delete语句.
DELETE FROM 表 WHERE id =1;
显式事务:事务具有明显的开启和结束的标记.
前提:必须先设置MySQL的事务默认设置(关闭自动提交开关).
SET autocommit=0;
(1):开启事务
START TRANSACTION;#可选的
(2):编写事务中的sql语句(SELECT INSERT UPDATE DELETE)
语句1;
语句2;
...
(3):结束事务
<1>:COMMIT;提交事务
<2>:ROLLBACK;回滚事务
SAVEPOINT 回滚点;设置保存点.
*/
-- 事务案例:
-- 创建账户表:
DROP TABLE IF EXISTS account;
CREATE TABLE account(
id INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(20),
money INT DEFAULT 0
);
-- 添加两条记录
INSERT INTO account VALUES (1, 'zhang3', 1000);
INSERT INTO account VALUES (2, 'li4', 1000);
SELECT * FROM account;
-- 不使用事务,正常转账:
UPDATE account SET money = money-500 WHERE `name` = 'zhang3';
UPDATE account SET money = money+500 WHERE `name` = 'li4';
-- 不使用事务,转账发生问题:
UPDATE account SET money = money-500 WHERE `name` = 'zhang3';
-- 此时发生问题,导致下一句sql无法执行:
UPDATE account SET money = money+500 WHERE `name` = 'li4';
-- 使用事务,封装转账逻辑
-- 关闭自动提交:
SET autocommit=0;
-- 开启事务:
START TRANSACTION;
-- 事务逻辑
UPDATE account SET money = money-500 WHERE `name` = 'zhang3';
UPDATE account SET money = money+500 WHERE `name` = 'li4';
-- 提交事务:
COMMIT;
/*
事务的四大特性:ACID
原子性(Atom):事务是最小的操作单位,不可分割,要么全部成功,要么全部失败.
一致性(Consistency):事务执行之前和执行之后,数据的状态必须保持一致性原则.
如:转账之前和转账之后,总钱数必须一致.
隔离性(Isolation):事务执行时是独立的,不受其他事务影响.
持久性(Durability):事务执行之后,数据状态的改变将是永久的.
*/
/*
事务的并发问题:
1.脏读:事务A读取了一个数据,这个数据是事务B修改的一个数据,此时事务B回滚了,
数据又恢复到原来的值,此时事务A读取的数据就是一个脏数据.
2.不可重复读:
事务A多次读取一个数据,其中有一次这个数据被事务B给修改了,
导致事务A前后两次读取的数据不一致.
3.幻读:
事务A读取(或修改)一个表的数据时,此时事务B向表中添加(或删除)了一条(或多条)
数据,导致事务A执行完之后,发现数据库中竟然还有(或少)数据没读取出来.好像产生
了幻觉一样.
注意:
(1)脏读和幻读比较容易混淆.
(2)脏读侧重数据被修改而导致的数据不准确.
(3)幻读侧重数据被添加或删除而导致的数据个数不一致.
*/
/*
事务的隔离级别:
前提:
(1)事务保证了一个逻辑单位操作的完整性和安全性.要么成,要么败,没有中间结果.
(2)但是事务和事务之间并发操作会出现问题:脏读,不可重复读,幻读.
(3)解决事务并发性需要引入一种策略:事务的隔离级别!
事务4级隔离级别:
(1)读未提交:read-uncommitted
(2)不可重复读:read-committed
(3)可重复读:repeatable-read
(4)串行化:serializable
事务隔离级别能解决的问题:
级别:问题(能否解决)
脏读不可重复读幻读
(1)1级别:read-uncommitted不能不能不能
(2)2级别:read-committed能不能不能
(3)3级别:repeatable-read能能不能
(4)4级别:serializable能能能
注意:
(1)第1级别只是一种级别,不能解决任何事务并发问题.
(2)MySQL默认是第3级别,Oracle默认是第2级别.
(3)级别越低,效率越高,执行速度越快,但是问题发生几率越大.
(4)第4级别,效率最差,数据安全性最好.
(5)级别的选择,根据企业项目需求.
*/
-- MySQL实例:
-- 查看隔离级别
SELECT
@@tx_isolation ;
-- 设置隔离级别
-- SET SESSION|GLOBAL TRANSACTION ISOLATION LEVEL 隔离级别;
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
-- 设置成最低级别:
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
-- 设置成最高级别:
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT @@tx_isolation ;
-- 查看数据库引擎:
SHOW ENGINES;
#1.演示事务的使用步骤
SELECT * FROM account;
USE db2;
-- 查看事务自动提交变量:
SELECT @@autocommit;
SET @@autocommit=0;# 关闭自动提交
-- 开启事务
START TRANSACTION;
-- 编写一组事务的语句
UPDATE account SET money = money - 500 WHERE id = 1;
UPDATE account SET money = money + 500 WHERE id = 2;
COMMIT;
-- 结束事务
ROLLBACK;# 要么回滚
COMMIT;# 要么提交
SELECT * FROM account;
#2.delete和truncate的在事务中的区别
-- delete
SET autocommit=0;# 关闭自动提交
# 开启事务
DELETE FROM account;# delete
ROLLBACK;# 回滚
-- truncate
START TRANSACTION;# 开启事务
TRUNCATE account;# TRUNCATE
ROLLBACK;# 回滚
/*
(1)delete删除数据,事务回滚,数据可恢复.
(2)turncate删除数据,事务回滚,数据不可恢复.
*/
#3.演示savepoint 的使用
SET autocommit=0;
START TRANSACTION;
DELETE FROM account WHERE id=25;
SAVEPOINT a;#设置保存点
DELETE FROM account WHERE id=28;
ROLLBACK TO a;#回滚到保存点
SELECT * FROM account;