#TCL
/*
Transaction control language 事务控制语言

事务:一个或一组sql语句组成一个执行单元,这个执行单元要么全部执行,要么全部不执行。


*/

SHOW ENGINES;#查看存储引擎,innodb存储引擎支持事务

/*
#事务的ACID属性:

1.原子性,atomicity
    原子性指事务是不可分割的工作单位,事务操作要么发生,要么都不发生。
    (捆绑执行)
2.一致性,consistency
    事务必须使数据库从一个一致性状态变换到另一个一致性状态。
3.隔离性,Isolation
    事务的隔离性指一个事务的执行不能被其他事务干扰;并发执行的各个事务之间不能互相干扰。
    (非绝对,有优先级)
4.持久性,durability
    持久性是指一个事务一旦被提交,对数据库数据改变是永久性的。
    其他操作和数据库障碍都不会对其有任何影响。
        
#事务的创建
隐式事务:事务没有明显的开启和结束的标记。
    比如:insert delete update 
    常用的DML语言和查询语句属于,隐式事务 autocommit 默认为on打开状态
    show variables like 'autocommit'; 显示变量autocommit的值

显式事务:事务具有明显的开启和结束标记
    前提:必须先设置自动提交功能为off;即 set autocommit = off/0;
    a.步骤1:开启事务
    set autocommit = 0;
    
    b.步骤2:编写事务中的sql语句(select insert update delete)
    语句1;
    语句2;
    ……
    
    c.步骤3
    commit; 提交事务
    rollback;回滚事务,即放弃提交

savepoint 节点名;设置节点,保存点
    搭配rollback to 节点名;使用,回滚至节点处




*/
USE test;
CREATE TABLE account(
    id INT PRIMARY KEY AUTO_INCREMENT,
    NAME VARCHAR(20),
    balance FLOAT
); 
INSERT INTO account VALUE(1,'007',1000),(NULL,'James',1000);

SET autocommit = off;
SHOW VARIABLES LIKE 'autocommit';

SELECT * FROM account;
#案例1:演示事务的使用步骤(提交)
SET autocommit = 0;#开启显示事务
START TRANSACTION;#此行可省略

UPDATE account SET balance=1500 WHERE NAME='007';#编写一组事务语句
UPDATE account SET balance=500 WHERE NAME='James';

COMMIT;#提交

#案例2:演示事务的使用步骤(放弃/回滚)
SET autocommit = 0;#开启显示事务
START TRANSACTION;#此行可省略

UPDATE account SET balance=1700 WHERE NAME='007';#编写一组事务语句
UPDATE account SET balance=300 WHERE NAME='James';

ROLLBACK;#提交

/*
数据库隔离级别

#若同时运行多个事务,当这些事务访问数据库相同的数据,若没采取隔离机制,会造成各种并发问题。
   脏读:两个事务T1、T2,T1读取了T2更新但还没有被提交的字段,之后若T2回滚,T1的内容是临时且无效的。
   不可重复读:T1读取字段后,T2更新了此字段,T1再次读取此字段,值就不同了。
   幻读:T1读取字段后,T2插入一些新的行,之后,若T1再次读取同一个表,就会多出几行数据。

#数据库事务的隔离性:数据库系统必须具有隔离并发运行各个事务的能力,使他们不会相互影响,避免各种并发问题。
   一个事务与其他事务隔离的程度称为隔离级别。数据库规定了多种事务隔离级别,不同隔离级别对应不同干扰程度
   隔离级别越高,数据一致性越好,但并发性越弱。
   
oracle 支持 READ COMMITED(默认) 、SERIALIZABLE 两种事务隔离级别

mysql 支持 REPEATABLE READ(默认) :可重复读,确保事务多次从一个字段读取相同值,这个事务持续其间,禁止其他事务对字段更新,可避免脏读和不可重复读。
     、READ COMMITED :读已提交数据,只允许事务读取已被其他事务提交的变更,只可避免脏读现象
     、READ UNCOMMITED :读未提交数据,允许事务读取未被其他事务提交的变更,不可避免脏读,不可重复读,幻读现象
     、SERIALIZABLE :串行化,确保事务可从一个表中读取相同行,在这个事务持续其间,禁止其他事务对该表的任何操作,可避免所有并发问题,但性能低下。

事务的隔离级别:
          脏读        不可重复读    幻读
read uncommitted:√                
read committed:  ×                
repeatable read: ×        ×        
serializable      ×             ×               ×



每启动一个mysql程序,都会获得一个单独数据库连接。
1.查看当前隔离级别:SELECT @@tx_isolation;
2.设置当前mysql连接的隔离级别:set transaction isolation leve [……/read commited/……];
3.设置数据库系统的全局的隔离级别:set global transaction isolation leve [……/read commited/……];
*/


SELECT @@tx_isolation;

#案例3.演示savepoint的使用
USE test;
SELECT * FROM account;

SET autocommit = 0;
START TRANSACTION;
DELETE FROM account WHERE id = 1;
SAVEPOINT a;
DELETE FROM account WHERE id = 2;
ROLLBACK TO a;


#delete和truncate在事务使用时的区别
/*
delete table 表
在事务结束中若用rollback,会进行回滚

truncate table 表
在事务结束中若用rollback,不会进行回滚
*/