TCL事务控制语句

事务属于TCL控制语言(Transaction Control Language )。

一. 事务概述

1.1 什么是事务?为什么要用事务?

一个事务是由一条或者多条sql语句构成,这一条或者多条sql语句要么全部执行成功,要么全部执行失败! 默认情况下,每条单独的sql语句就是一个单独的事务!

举例: 银行转账!张三转10000块到李四的账户,这其实需要两条SQL语句: 给张三的账户减去10000元; 给李四的账户加上10000元。 如果在第一条SQL语句执行成功后,在执行第二条SQL语句之前,程序被中断了(可能是抛出了某个异常,也可能是其他什么原因),那么李四的账户没有加上10000元,而张三却减去了10000元。这肯定是不行的! 你现在可能已经知道什么是事务了吧!事务中的多个操作,要么完全成功,要么完全失败!不可能存在成功一半的情况!也就是说给张三的账户减去10000元如果成功了,那么给李四的账户加上10000元的操作也必须是成功的;否则给张三减去10000元,以及给李四加上10000元都是失败的!

1.2 MySQL中的存储引擎

1、存储引擎的概念:在mysql中的数据用各种不同的技术存储在文件(或内存)中。 2、通过show engines;来查看mysql支持的存储引擎。 3、 在mysql中用的最多的存储引擎有:innodb, myisam ,memory 等。其中innodb支持事务,而 myisam、memory等不支持事务。

二.事务的分类

1.隐式事务:没有明显的开启和结束标记,比如dml语句的insert、update、delete语句本身就是一条事务 insert into stuinfo values(1,’Jack’,’男’,’123@qq.com’,12);

2.显式事务:具有明显的开启和结束标记,一般由多条sql语句组成,必须具有明显的开启和结束标记 步骤: 1、开启事务 取消隐式事务自动开启的功能

2、编写事务需要的sql语句(1条或多条) — insert into stuinfo values(1,’Mark’,’男’,’123@qq.com’,12); — insert into stuinfo values(2,’Lisa’,’女’,’123@qq.com’,12);

3、结束事务 提交事务或回滚事务

三.事务的四大特性(ACID)

原子性(Atomicity):事务中所有操作是不可再分割的原子单位。事务中所有操作要么全部执行成功,要么全部执行失败。 一致性(Consistency):事务执行后,数据库状态与其它业务规则保持一致。如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的。 隔离性(Isolation):隔离性是指在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰。 持久性(Durability):一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证通过某种机制恢复数据。

总结: — 原子性(Atomicity):指在事务中包含所有操作,要么都做,要么都不做(不可分割)

— 一致性(Consistency):数据的改变保证一致

— 隔离性(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改的能力,防止多个事务并发执行时由于交叉执行而导致数据的不一致。

— 持久性(Durability):事务处理结束之后,对数据的修改是永久的,即便你的系统出现故障,也不会丢失。(将数据存在了磁盘上)

四.MySql中的事务

在默认情况下,MySQL每执行一条SQL语句,都是一个单独的事务。如果需要在一个事务中包含多条SQL语句,那么需要开启事务和结束事务。 — 开启事务:start transaction;

— 结束事务:commit或rollback;

— 断点 savepoint 断点 rollback to 断点 在执行SQL语句之前,先执行strat transaction,这就开启了一个事务(事务的起点),然后可以去执行多条SQL语句,最后要结束事务,commit表示提交,即事务中的多条SQL语句所做出的影响会持久化到数据库中。或者rollback,表示回滚,即回滚到事务的起点,之前做的所有操作都被撤消了。

由于事务是自动开启的,需要先取消事务的自动开启 — 查看含有auto的变量 SHOW VARIABLES LIKE ‘%autocommit%’

— 取消事务自动开启 SET autocommit = 0;

案例: 创建事务要用到的表 CREATE TABLE account(

  1. id INT PRIMARY KEY AUTO_INCREMENT,
  2. NAME VARCHAR(30),
  3. balance double(10,2)

);

INSERT INTO account(NAME,balance) VALUES(‘zs’, 100000);

INSERT INTO account(NAME,balance) VALUES(‘ls’, 100000);

SELECT * FROM account;

Ø 演示事务执行失败 — 案例一:回滚 事务执行失败 START TRANSACTION;

UPDATE account SET balance=balance-10000 WHERE id=1;

UPDATE account SET balance=balance+10000 WHERE id=2;

ROLLBACK;

— 案例二:退出mysql客户端 事务执行失败! START TRANSACTION;

UPDATE account SET balance=balance-10000 WHERE id=1;

UPDATE account SET balance=balance+10000 WHERE id=2;

Ø 演示事务执行成功 START TRANSACTION;

UPDATE account SET balance=balance-10000 WHERE id=1;

UPDATE account SET balance=balance+10000 WHERE id=2;

COMMIT;

五.事务的隔离级别

5.1 事务并发问题如何发生?

当多个事务同时操作同一个数据库的相同数据时

5.2 事务的并发问题有哪些?

对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种并发问题: — 多个事务同时处理,会遇到的现象: 脏读:用户读了修改后未提交的数据(rollback产生)

不可重复读:读取同一条记录,但是两次数据不一样(两次提交同一条记录)

幻读:读取同一张表,两次记录数不一样(两次提交不同的记录)

5.3 如何避免事务的并发问题?

数据库事务的隔离性: 数据库系统必须具有隔离并发运行各个事务的能力, 使它们不会相互影响, 避免各种并发问题。一个事务与其他事务隔离的程度称为隔离级别. 数据库规定了多种事务隔离级别, 不同隔离级别对应不同的干扰程度, 隔离级别越高, 数据一致性就越好, 但并发性越弱。 Oracle 支持的 2 种事务隔离级别:READ COMMITED, SERIALIZABLE。 Oracle 默认的事务隔离级别为: READ COMMITED。 Mysql 支持 4 种事务隔离级别. Mysql 默认的事务隔离级别为: REPEATABLE READ TCL事务控制语句 - 图1

— 通过设置事务的隔离级别 读未提交READ UNCOMMITTED:允许幻读和不可重复读,脏读

读提交READ COMMITTED:允许幻读和不可重复读,但是不允许脏读 —读提交:本次操作若发生改变了,必须提交,其他人才能看见改变的(Oracle默认)

重复读REPEATABLE READ:允许幻读,但是不允许不可重复读和脏读(MySQL默认)

串行化读SERIALIZABLE:都不允许幻读和不可重复读,脏读 —串行化读:首先重新建立连接,只管自己本次事务操作,不管外部数据的变化(即使提交也看不见)

每启动一个 mysql 程序, 就会获得一个单独的数据库连接. 每 个数据库连接都有一个全局变量@@tx_isolation, 表示当前的事务隔离级别。 — mysql中默认 第三个隔离级别 repeatable read — oracle中默认 第二个隔离级别 read committed

— 查看当前的隔离级别 select @@tx_isolation;

— 设置 当前会话 | 数据库系统的全局的 MySQL连接的隔离级别 set session|global transaction isolation level 隔离级别;

读未提交READ UNCOMMITTED:允许幻读和不可重复读,脏读

TCL事务控制语句 - 图2

读提交READ COMMITTED:允许幻读和不可重复读,但是不允许脏读

TCL事务控制语句 - 图3

重复读REPEATABLE READ:允许幻读,但是不允许不可重复读和脏读(MySQL默认)

不允许不可重复读和脏读 TCL事务控制语句 - 图4

允许幻读 TCL事务控制语句 - 图5

串行化读SERIALIZABLE:都不允许幻读和不可重复读,脏读

TCL事务控制语句 - 图6