一、MySQL事务
MySQL事务控制语言(Transaction Control Language)简称:事务。事务由单独单元的一个或多个sQL语句组成,在这个单元中,每个MySQL语句是相互依赖的。而整个单独单元作为一个不可分割的整体,如果单元中某条SQL语句一且执行失败或产生错误,整个单元会回滚。所有受到影响的数据将返回到事物开始以前的状态;如果单元中的所有SQL语句均执行成功,则事物被顺利执行。[一个或一组sql语言组成的一个执行单元,这个执行单元要么全部执行,要么全部不执行。]
1、常见支持事务的存储引擎
- show engines;
2、事务必须满足4个属性(ACID)
一般来说,事务是必须满足4个属性(ACID)::原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。
- 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
- 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
- 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
- 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
注意:在 MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作。
因此要显式地开启一个事务务须使用命令 BEGIN 或 START TRANSACTION,
或者执行命令 SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交。
3、事务的创建
隐式事务:事务没有明显的开启和结束的标记。比如insert、update、delete语句
- delete from 表 where id=1;
- SHOW VARIABLES LIKE 'autocommit' ; # (结果:on开启/off关闭)
显式事务:事务具有明显的开启和结束的标记。前提:必须先设置自动提交功能为禁用
步骤1:
- set autocommit =0; #临时禁止事务自动提交
- start transaction; #开启显式事务[可选]
步骤2:
- 编写事务中的sq1语句(select、insert、update、delete)
语句1;语句2;.......
步骤3:结束事务或者回滚事务(当执行回滚时磁盘中的数据并没有发生改变)
- commit; #提交事务
- 或者
- rollback; #回滚事务
4、无隔离机制的多事务运行后果
对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会导致各种并发问题:
- 脏读:对于两个事务T1,T2,T1读取了已经被T2更新但还没有被提交的字段之后,若T2回滚,T1读取的内容就是临时且无效的。
- 不可重复读:对于两个事务T1,T2,T1读取了一个字段,然后T2更新了该字段之后,T1再次读取同一个字段,值就不同了。
- 幻读:对于两个事务T1,T2,T1从一个表中读取了一个字段,然后T2在该表中插入了一些新的行之后,如果T1再次读取同一个表,就会多出几行.
5、数据库事务的隔离性
数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题。一个事务与其他事务隔离的程度称为隔离级别。数据库规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱。
6、mysql数据库提供的4种事务隔离级别
mysql> select @@tx_isolation; #查看当前隔离使用级别,mysql默认是这个
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
#更改隔离级别
mysql> set session transaction isolation level Serializable;
Query OK, 0 rows affected (0.00 sec)
mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| SERIALIZABLE |
+----------------+
1 row in set, 1 warning (0.00 sec)
Read Uncommited
- 在RU模式下,即使事务没有commit,在其他事务中仍可以读到未提交的数据。
- RU是所有隔离级别中最低的一种。RU模式会导致脏读
Read Commited
- RC模式下,事务只能读取到已经commit的数据。
- 比如事务a在执行时,如果事务b没有提交,a是读不到b的数据的。如果b提交a便能读到b修改的数据。
- RC可以避免脏读,但是会导致不可重复读。
- 大部分系统使用的是RC模式
Repeatable
- RR模式下,事务的多次Read不会受其他事务的影响(无论提交与否)
- 可以理解为RR模式下事务a在创建的时候获取了一次当前时刻数据的快照,快照不受其余事务的影响。
- RR模式可能会导致幻读,因为无法感知其余事务,可能导致重复的插入。
- mysql innoDB的RR模式可以一定程度避免幻读,该特性是通过
间隙锁(gap lock)
来实现的。
Serializable
- 串行化,顾名思义,是将所有读写操作完全串行。
- 串行化是所有隔离级别中最高的
- 每次读都需要获得表级共享锁,读写相互都会阻塞
- 串行化对资源的开销大,对并发支持不好,只在,某些场景下使用。
7、给事务设置回滚节点 savepoint
演示savepoint的使用
SET autocommit=0;
START TRANSACTION;
DELETE FROM account WHERE id=25;
SAVEPOINT a;#设置保存点
DELETE EROM account WHERE id=28;
ROLLBACK TO a;#回滚到保存点
8、delect 和truncate在事务中的不同效果
delect语句支持回滚,truncate语句不支持回滚
set autocommit = 0; #临时禁止事务自动提交
start transaction; #开启显式事务[可选]
delect from tablename ; #sql执行语句
rollback; #回滚事务
select * from tablename; #此时回滚事务生效,并没有清空表
set autocommit = 0; #临时禁止事务自动提交
start transaction; #开启显式事务[可选]
truncate table tablename ; #sql执行语句
rollback; #回滚事务
select * from tablename; #此时回滚事务无效,表已经清空