概念
TCL (Transaction Control Language) :事务控制语言
事务:一个或一组sql语句组成一个执行单元,这个执行单元要么全部执行,要么全部不执行。
MySQL的事务支持不是绑定在MySQL服务器本身,而是与存储引擎相关,下面是两个常用引擎:
- MyISAM:不支持事务,用于只读程序提高性能
- InnoDB:支持ACID事务、行级锁、并发
事务的特性:ACID
- 原子性(A):一个事务不可再分割,要么都执行要么都不执行
- 一致性(C):一个事务执行会使数据从一个一致状态切换到另外一个一致状态(整体始终一致)
- 隔离性(I):一个事务的执行不受其他事务的干扰
- 持久性(D):一个事务一旦提交,则会永久的改变数据库的数据.
案例:转账
张无忌 1000
赵敏 1000
update 表 set 张无忌的余额=500 where name='张无忌'
发生意外,报错什么的
update 表 set 赵敏的余额=1500 where name='赵敏'
转账业务,张无忌给赵敏转账500。首先扣除张无忌的账户的钱,然后增加赵敏账户的钱。
如果不使用事务中途发生了错误,结果是张无忌的钱少了,而赵敏的钱没增加。这就违背了一致性原则。
==========
事务操作
- 查看服务器引擎:
SHOW ENGINES;
- 查看自动提交参数设置:
SHOW VARIABLES LIKE 'autocommit';
MySQL默认操作模式就是autocommit自动提交模式。这就表示除非显式地开启一个事务,否则每个查询都被当做一个单独的事务自动执行。
- 显示地开启一个事务:
START TRANSACTION;
- 显示开启事务的操作是:
START TRANSACTION; #开启一个事务 update 表 set 张无忌的余额=500 where name='张无忌' update 表 set 赵敏的余额=1500 where name='赵敏' COMMIT; #提交事务
当autocommit开启时,如果不显示开启事务,这时候使用 COMMIT 和 ROLLBACK 是不起作用的。
- 设置autocommit关闭:
SET autocommit=0; 或者 SET autocommit=off;
自动提交关闭后,每次修改数据库后必须手动进行提交或回滚。
这种设置是会话(session)级别的,即每个连接都有各自的配置。
关闭了自动提交后,如果更新了数据库(CUD操作)就会自动开启一个事务,直到执行COMMIT或者ROLLBACK语句结束事务。
==========
事务的隔离级别
对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种并发问题:
- 脏读(Drity Read):某个事务已更新一份数据但是未提交,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。
- 不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间另一个事务对数据进行了更新。
- 幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。
数据库事务的隔离性: 数据库系统必须具有隔离并发运行各个事务的能力, 使它们不会相互影响, 避免各种并发问题.
隔离级别:一个事务与其他事务隔离的程度称为隔离级别. 数据库规定了多种事务隔离级别, 不同隔离级别对应不同的干扰程度, 隔离级别越高, 数据一致性就越好, 但并发性越弱.
数据库提供的4 种事务隔离级别:
1. Read Uncommitted(读取未提交)
- 在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。脏读、不可重复读和幻读都会出现。
- 本隔离级别很少用于实际应用,因为会出现很多问题,而它的性能也不比其他级别好多少。
2.Read Committed(读取已提交)
- 只允许事务读取已经被其他事务提交的变更,避免了脏读。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。
- 这种隔离级别可能会出现不可重复读(Nonrepeatable Read)问题,因为可能会有其他事务在该事务处理其间可能会有新的commit,所以同一select可能返回不同结果。
- 而幻读(Phantom Read)也无法避免。
这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)
3. Repeatable Read(可重复读)
- 可避免脏读和不可重复读问题
- 无法避免幻读(Phantom Read)
- InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制可解决幻读(Phantom Read)问题。
这是MySQL的默认事务隔离级别,一般Mysql应用都会使用这个隔离级别。
4.Serializable(可串行化)
- 这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁,如果一个事务中使用到了某个表,就会将之锁住,其他的事务对于这个表的操作只能等待。在这个级别,可能导致大量的超时现象和锁竞争,开启事务后锁定表或者行,不让其他对象获取到,直到事务提交才释放锁。
- 这种隔离级别可以避免上面所有的并发问题,但是性能十分低下。
----------
在Mysql中设置隔离级别
Oracle 支持的2 种事务隔离级别:READCOMMITED, SERIALIZABLE。
Oracle 默认的事务隔离级别为: READ COMMITED
Mysql 支持4 种事务隔离级别.Mysql 默认的事务隔离级别为: REPEATABLE READ
每启动一个mysql 程序, 就会获得一个单独的数据库连接. 每个数据库连接都有一个全局变量@@tx_isolation, 表示当前的事务隔离级别.
查看当前连接的隔离级别:
SELECT @@tx_isolation; #或者 select @@session.tx_isolation;
- 设置当前会话隔离级别
set tx_isolation='repeatable-read' #或者 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
- 查看系统当前隔离级别
select @@global.tx_isolation;
- 设置系统当前隔离级别
修改mysql.ini配置文件,在最后加上
#可选参数有:READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ, SERIALIZABLE. [mysqld] transaction-isolation = REPEATABLE-READ
select @@global.tx_isolation;
select @@global.tx_isolation;