07、事务(TCL)

07、事务(TCL)

1、什么是事务(Transaction)

一个事务是一个完整的业务逻辑单元,不可拆分。

比如:银行转账,A账户给B账户转账10000,需要执行2条update的语句。

​ A余额减少10000

​ B余额增加10000

以上两条数据,要么同时成功,要么同时失败。

要想保证以上两条数据,要么同时成功,要么同时失败,就需要使用数据库的事务机制。

2、事务什么时候使用

和事务相关的语句只有DML语句。(insert,delete,update)

因为DML语句都是和数据库表当中的数据有关的,事务的存在就是为了保证数据的完整性、安全性。

如果所有的业务都可以一条DML语搞定,就不需要事务了。

3、事务的四大特性:ACID

1 、原子性
事务是数据库的逻辑工作单位, 不可再分。
2 、一致性
事务必须保证多条DML语句要么同时成功,要么同时失败。
3 、隔离性
一个事务的执行不能其它事务干扰。
4 、持续性
持久性就是最终数据必须持久化到硬盘文件中,事务才算完成。

4、事务之间的隔离性

隔离级别包括4个:

  • 第一级别:读未提交(Read Uncommitted)
    • 可以读取对方未提交的数据
    • 存在脏读(Dirty Read)现象,读到了脏数据,读到的数据可能已经改变了。
  • 第二级别:读已提交(Read Committed)
    • 大多数数据库系统默认的初始状态,Oracle数据库默认级别,mysql是第三级别初始。
    • 可以读取对方提交后的数据
    • 解决了脏读现象
    • 存在不可重复读,不可重读读意味着我们同一事务执行完全相同的select语句时可能看到不一样的结果。
  • 第三级别:可重复读(Repeatable Read)
    • 这是MySQL的默认事务隔离级别
    • 它确保同一事务的多个实例在并发读取数据时,看到同样的数据行
    • 解决了不可重复读
    • 存在幻读现象(Phantom Read),当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行
  • 第四级别:可串行化/序列化(serializable)
    • 最高的隔离级别
    • 它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它在每个读的数据行上加上共享锁。
    • 缺点:
      • 效率低
      • 可能导致大量的超时现象和锁竞争

5、演示事务

mysql默认情况是自动提交的。

关闭自动提交:

start transaction;

准备表:

drop table if exists t_user;
create table t_user(
	id int primary key auto_increment,
	username varchar(255)
);

演示:

(1)mysql中事务是自动提交的:

insert t_user (username) values('张三');
select * from t_user;
+----+----------+
| id | username |
+----+----------+
|  1 | 张三     |
+----+----------+

rollback;
select * from t_user;
+----+----------+
| id | username |
+----+----------+
|  1 | 张三     |
+----+----------+

(2)关闭自动提交事务:start transaction;

​ rollback: 回滚到开始事务的地方

start transaction;
insert t_user (username) values('李四');
select * from t_user;
+----+----------+
| id | username |
+----+----------+
|  1 | 张三     |
|  2 | 李四     |
+----+----------+

rollback;
select * from t_user;
+----+----------+
| id | username |
+----+----------+
|  1 | 张三     |
+----+----------+

(3)提交 commit,把这次事务提交。

rollback 只能回滚到这次事务的开始位置,如果已经提交了,就不能在回滚了。

start transaction;
insert t_user (username) values('李四');
insert t_user (username) values('王五');
select * from t_user;
+----+----------+
| id | username |
+----+----------+
|  1 | 张三     |
|  2 | 李四     |
|  3 | 王五     |
+----+----------+

commit;
select * from t_user;
+----+----------+
| id | username |
+----+----------+
|  1 | 张三     |
|  2 | 李四     |
|  3 | 王五     |
+----+----------+

rollback;
select * from t_user;
+----+----------+
| id | username |
+----+----------+
|  1 | 张三     |
|  2 | 李四     |
|  3 | 王五     |
+----+----------+

(4)演示隔离级别

设置事务的全局隔离级别:

set global transaction isolation level read uncommitted;

查看事务的全局隔离界别:

SELECT @@global.transaction_isolation;
+--------------------------------+
| @@global.transaction_isolation |
+--------------------------------+
| READ-UNCOMMITTED               |
+--------------------------------+

1)演示 读未提交(Read Uncommitted)

先设置隔离界别:设置完成之后需要关闭

mysql -uroot -p123456
use bookshop
set global transaction isolation level read uncommitted;
SELECT @@global.transaction_isolation;
+--------------------------------+
| @@global.transaction_isolation |
+--------------------------------+
| READ-UNCOMMITTED               |
+--------------------------------+

需要开启两个窗口演示

窗口1:

mysql -uroot -p123456
use bookshop
start transaction;
select * from t_user;
insert t_user(username) values ('麻六');

窗口2:

mysql -uroot -p123456
use bookshop

start transaction;

select * from t_user;				//起始的查询
+----+----------+
| id | username |
+----+----------+
|  1 | 张三     |
|  2 | 李四     |
|  3 | 王五     |
|  4 | 王五     |
+----+----------+
select * from t_user;				//未提交之前的查询
+----+----------+
| id | username |
+----+----------+
|  1 | 张三     |
|  2 | 李四     |
|  3 | 王五     |
|  4 | 王五     |
|  5 | 麻六     |
+----+----------+

2)演示读已提交(Read Committed)

先设置隔离界别:设置完成之后需要关闭

mysql -uroot -p123456
use bookshop
set global transaction isolation level read committed;
SELECT @@global.transaction_isolation;
+--------------------------------+
| @@global.transaction_isolation |
+--------------------------------+
| READ-COMMITTED                 |
+--------------------------------+

需要开启两个窗口演示

窗口1:

mysql -uroot -p123456
use bookshop
start transaction;
select * from t_user;
insert t_user(username) values ('唐三');
commit;

窗口2:

mysql -uroot -p123456
use bookshop

start transaction;

select * from t_user;			//起始的查询
+----+----------+
| id | username |
+----+----------+
|  1 | 张三     |
|  2 | 李四     |
|  3 | 王五     |
|  4 | 王五     |
+----+----------+
select * from t_user;			//未提交之前的查询
+----+----------+
| id | username |
+----+----------+
|  1 | 张三     |
|  2 | 李四     |
|  3 | 王五     |
|  4 | 王五     |
+----+----------+

select * from t_user;			//提交之后的查询
+----+----------+
| id | username |
+----+----------+
|  1 | 张三     |
|  2 | 李四     |
|  3 | 王五     |
|  4 | 王五     |
|  6 | 唐三     |
+----+----------+

3)演示可重复读(Repeatable Read)

先设置隔离界别:设置完成之后需要关闭

mysql -uroot -p123456
use bookshop
set global transaction isolation level Repeatable Read;
SELECT @@global.transaction_isolation;
+--------------------------------+
| @@global.transaction_isolation |
+--------------------------------+
| REPEATABLE-READ                |
+--------------------------------+

需要开启两个窗口演示

窗口1:

mysql -uroot -p123456
use bookshop
start transaction;
select * from t_user;
delete from t_user;
commit;

窗口2:

mysql -uroot -p123456
use bookshop
start transaction;
select * from t_user;			//起始的查询
+----+----------+
| id | username |
+----+----------+
|  1 | 张三     |
|  2 | 李四     |
|  3 | 王五     |
|  4 | 王五     |
|  6 | 唐三     |
+----+----------+

select * from t_user;			//提交之后的查询
+----+----------+
| id | username |
+----+----------+
|  1 | 张三     |
|  2 | 李四     |
|  3 | 王五     |
|  4 | 王五     |
|  6 | 唐三     |
+----+----------+

4)演示可串行化/序列化(serializable)

先设置隔离界别:设置完成之后需要关闭

mysql -uroot -p123456
use bookshop
set global transaction isolation level serializable;
SELECT @@global.transaction_isolation;
+--------------------------------+
| @@global.transaction_isolation |
+--------------------------------+
| SERIALIZABLE                   |
+--------------------------------+

需要开启两个窗口演示

窗口1:

mysql -uroot -p123456
use bookshop
start transaction;
insert t_user(username) values ('唐三');
commit;

窗口2:

mysql -uroot -p123456
use bookshop
start transaction;
select * from t_user;			//起始的查询
+----+----------+
| id | username |
+----+----------+
|  7 | 张三     |
+----+----------+

select * from t_user;			//提交之前的查询
//会一直卡在这块,当窗口一提交的时候,才能接着运行

//提交之后
+----+----------+
| id | username |
+----+----------+
|  7 | 张三     |
+----+----------+
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值