事务
此系列记录PN视频学习笔记
* 本博客涉及到的数据为bjpowernode.sql,SQL文见MySQL入门(9)文末。
* 该数据有三张表,分别是部门表dept(deptno部门编号、dname部门名称、loc位置)、
员工表emp(empno工号、ename员工姓名、job职位、mgr直属领导工号、
hiredate入职日期、sal月薪、comm补贴、deptno部门编号)、
薪水等级表salgrade(grade等级、losal区间下限、hisal区间上限)
事务
1、什么是事务?
-事务对应的英语单词:Transaction
-事务: * 一个‘最小’的‘不可再分’的工作单元。
* 通常一个事务对应了一个完整的业务。【例如:银行账户转账业务,该业务就是一个最小的工作单元】
* 而一个完整的业务需要一个批量的DML(insert,update,delete)语句共同联合完成
* 事务只和DML语句有关系,或者说DML语句才有事务
* 以上所描述的‘批量的DML语句’共有多少条DML语句,这个和业务逻辑有关系,业务逻辑不同,DML语句的个数不同
2、关于银行账户转账操作,账户转账是一个完整的业务,最小的单元,不可再分,也就是说银行账户转账是一个业务。
t_act账户表
actno balance
-------------------------------------
act-001 50000.0
act-002 10000.0
执行转账操作(10000):
updatet_act set balance = 40000.0 where actno = ‘act-001’;
updatet_act set balance = 20000.0 where actno = ‘act-002’;
以上两条DML语句要求必须同时成功或者同时失败,最小单元,不可再分。当第一条DML语句执行成功之后,并不能将底层数据库中第一个账户的数据修改,只是将操作记录了一下,这个记录是在内存中完成的,当第二条DML执行成功之后,和底层数据文件的数据完成同步。若第二条DML语句执行失败,清空所有历史操作记录。要完成以上功能,必须借助事务。
3、事务的四个特征(ACID)
-原子性(A)
*事务是最小的工作单元,不可再分
-一致性(C)
*事务要求所有的DML语句操作的时候,必须同时成功或者同时失败
-隔离性(I)
*事务A和事务B之间具有隔离
-持久性(D)
*是事务的保证,事务终结的标志。【内存中的数据持久到硬盘文件中】
4、关于一些术语【不是SQL语句】
-开启事务: start transaction
-结束事务: end transaction
-提交事务: commit transaction
-回滚事务: rollback transaction
5、和事务有关的两条重要的SQL语句【TCL】
commit 提交
rollback 回滚
6、事务开启和结束的标志
-开始的标志:
任何一条DML(insert,update,delete)语句的执行,标志的事务的开启
-结束的标志:
提交或者回滚
提交:成功的结束,将所有DML操作历史记录和底层硬盘文件中的数据进行同步
回滚:失败的结束,将所有DML语句操作历史记录全部清空
7、重点:
在事务进行过程中,未结束之前,DML语句是不会更改底层数据库文件的数据,只是将历史操作记录一下,在内存中完成记录,只有在事务结束的时候,而且是成功的结束的时候才会修改底层硬盘文件中的数据。
8、在MYSQL数据库管理系统中,事务的提交和回滚的演示
-在MYSQL数据库管理系统中,默认情况下,事务是自动提交的额,也就是说,只要执行一条DML语句,开启事务即提交事务。
-这种自动提交机制是可以关闭的【关闭的第一种方式】
starttransaction; 手动开启事务
DML语句...
DML语句...
DML语句...
DML语句...
commit; 手动提交事务【事务成功的结束】
start transaction; 手动开启
DML语句...
DML语句...
DML语句...
DML语句...
rollback; 手动回滚事务【事务失败的结束】
-关闭自动提交的第二种方式
setaotucommit = on/off;
setsession aotucommit = on/off;
mysql>show variables like '%commit%';
以上打开和关闭自动提交机制,只对当前会话有效
+-----------------------------------------+-------+
| Variable_name | Value |
+-----------------------------------------+-------+
| autocommit | OFF |
| binlog_group_commit_sync_delay | 0 |
| binlog_group_commit_sync_no_delay_count | 0 |
| binlog_order_commits | ON |
| innodb_api_bk_commit_interval | 5 |
| innodb_commit_concurrency | 0 |
| innodb_flush_log_at_trx_commit | 1 |
| slave_preserve_commit_order | OFF |
+-----------------------------------------+-------+
mysql> set autocommit = on;
mysql> show variables like '%commit%';
+-----------------------------------------+-------+
| Variable_name | Value |
+-----------------------------------------+-------+
| autocommit | ON |
| binlog_group_commit_sync_delay | 0 |
| binlog_group_commit_sync_no_delay_count | 0 |
| binlog_order_commits | ON |
| innodb_api_bk_commit_interval | 5 |
| innodb_commit_concurrency | 0 |
| innodb_flush_log_at_trx_commit | 1 |
| slave_preserve_commit_order | OFF |
+-----------------------------------------+-------+
9、事务的四个特性——隔离性(isolation)
9.1事务A和事务B之间具有一定的隔离性
9.2 隔离性的四个级别:
-read uncommited 读未提交
-read commited 读已提交
-repeatable read 可重复读
-serializable 串行化
9.3 read uncommited 读未提交
-事务A和事务B ,事务A未提交的数据,事务B可以读取到。
-这里读取到的数据可以叫做‘脏数据’,或者叫‘dirty read’
-这种隔离级别是最低级别,这种级别一般都是在理论上存在的,数据库默认的隔离级别,一般都是高于该隔离级别的。
9.4 read commited 读已提交
-事务A和事务B ,事务A提交的数据,事务B才能读取到。换句话说:对方事务提交之后的数据,当前事务才能读取到。
-这种隔离级别可以避免脏数据,高于上面的读未提交的隔离级别。
-这种隔离级别会导致‘不可重复读取’
-oracle数据库管理系统默认的隔离级别
9.5 repeatable read 可重复读
- 事务A和事务B ,事务A提交之后的数据,事务B读取不到。换句话说,对方提交之后的数据我还是读取不到。
- 事务B是可重复读取数据的,不同时间读取一条数据得到一个结果(缓存中的数据)
- 这种隔离级别可以避免‘藏独和不可重复读取’,达到可重复读取,高于读已提交隔离级别
- 虽然可以达到‘可重复读’的效果,但是会导致‘幻想读’
- MYSQL数据库管理系统默认的隔离级别
9.6 serializable 串行化
-事务A和事务B,事务A在操作数据库表中数据的时候,事务B只能排队等待,事务A和事务B是串行执行,不再并发
-这种事务隔离级别一般很少使用,吞吐量太低,用户体验不好
-这种隔离级别可以避免‘幻想读’,每一次读取的都是数据库表中真是的记录
10、设置事务的隔离级别
10.1 第一种方式:修改my.ini配置文件
使用transaction-isolation选项来设置服务器的缺省事务隔离级别
可选值:read-uncommited;read-commited;repeatable-read;serializable
------------------my.ini-------------------------
[mysqld]
transaction-isolation= read-uncommited
10.2 第二种方式:使用命令方式设置事务的隔离级别
可选值:read-uncommited;read-commited;repeatable-read;serializabl
set [无/session/global] transaction isolation level read-uncommited;
默认是会话级(设置隔离级别作用于当前回话),而不是全局级(设置隔离级别作用于全局)。
11、查看事务的隔离级别
查看当前回话的事务隔离级别
select @@tx isolation;
select@@session isolation;
查看当前全局的事务隔离级别
select @@globalisolation;
12、并发事务与隔离级别示例
12.1 读未提交 read uncommited
会话1 会话2
------------------------------------------------------------------------------------------------------------
setglobal transaction isolation level read uncommited;
select @@tx isolation;(若报错,需要重新打开)
usebjpowernode; use bjpowernode
starttransaction; start transaction;
inserttable t_user(name) values(‘king’); select * from t_user;(查询到)
12.2 读已提交 read commited
会话1 会话2
------------------------------------------------------------------------------------------------------------
setglobal transaction isolation level read commited;
select@@tx isolation;
usebjpowernode; use bjpowernode
starttransaction; start transaction;
inserttable t_user(name) values(‘ford’); select * from t_user;(未查询到)
commit; select * from t_user;(查询到)
12.3 可重复读 repeatable read
会话1 会话2
------------------------------------------------------------------------------------------------------------
setglobal transaction isolation level repeatable read;
select@@tx isolation;
usebjpowernode; use bjpowernode
starttransaction; start transaction;
select* from t_user; select * from t_user;(可查询)
insert table t_user(name) values(‘luzhishen’);
commit; select * from t_user;(和上一条结果一致)