Mysql事件介绍


概念:mysql中,事务是一个最小的不可分割的工作单元。事务能够保证一个业务的完整性。

以银行转账为例:

-- A支出100,B收款100
update user set money = money-100 where name = 'A';
update user set money = money+100 where name = 'B';

如果执行过程中只有一条执行成功,另一条失败,那么系统数据就会出现错误。

所以在开发过程中,有时就要求多条sql语句,同时成功或者失败(不可分割),这是事务要做的事情。

mysql中如何控制事务?

1. autocommit 自动提交

  • mysql 默认是开启的
select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            1 |
+--------------+
1 row in set (0.01 sec)
-- 自动提交:但我们去执行一个sql语句的时候,效果会立即提现,且不会回滚
-- 事务回滚值的是撤销sql语句执行效果,
rollback;
-- 即执行之后,即使执行rollback;语句,也不会这小执行效果。

-- 要想取消操作,要设置autocommit = 0,关闭自动提交;
set autocommit = 0;
insert into user values(2,'b',100);
select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  2 | b    |   100 |
+----+------+-------+
-- 再回滚,那么可以撤销执行
rollback;
select * from user;
Empty set (0.00 sec)
-- 再次插入数据,并手动提交,再回滚也不能撤销
insert into user values(2,'b',100);
commit;
rollback;
select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  2 | b    |   100 |
+----+------+-------+
1 row in set (0.00 sec)

​ 以上例子说明自动提交能防止事务回滚,从一方面说明,一旦提交(自动或者手动),那么都 无法回滚(持久性)。

综上所述,事务包括:

  • 自动提交 : @@autocommit=1;
  • 手动提交:commit;
  • 事务回滚:rollback;

事务给我们提供了一个反悔的机会

回过头来看转账,通过取消自动取消,在进行rollback可以取消操作

update user set money = money-100 where name = 'A';
update user set money = money+100 where name = 'B';
rollback;

2. 使用begin 或者 start transaction来手动开启一个事务

begin;
update user set money = money-100 where name = 'A';
update user set money = money+100 where name = 'B';
rollback;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |  1000 |
|  2 | b    |  1000 |
+----+------+-------+
-- 把begin换成transaction可以达到同样的效果。
-- 一旦commit, 那么事务已经结束,rollback也没用

总结:事务四大特征ACID

  • A(atomic)原子性:事务是最小的单位,不可以分割
  • C(consistency)一致性:同一事务中的sql语句要同时成功或者同时失败
  • I(isolation):事务1和事务2之间是隔离的。
  • D(durability)持久性:事务一旦结束(commit, rollback),就不可以返回。
  • 事务开启方式:修改 autocommit =0,begin,transaction
  • 事务结束方式:rollback,commit

事务隔离性

1. read uncommitted 读未提交的,可能会出现脏读

有事务A和事务B,操作过程中事务A没有提交,事务B可以看到事务A的操作结果

首先来看如何看隔离级别

select @@global.transaction_isolation;
+--------------------------------+
| @@global.transaction_isolation |
+--------------------------------+
| REPEATABLE-READ                |
+--------------------------------+
1 row in set (0.01 sec)

修改隔离级别

set global transaction isolation level read uncommitted;
select @@global.transaction_isolation;
+--------------------------------+
| @@global.transaction_isolation |
+--------------------------------+
| READ-UNCOMMITTED               |
+--------------------------------+
1 row in set (0.00 sec)

小明向店铺转账800

start transaction;
update user set money = money-800 where name = '小明';
update user set money = money+800 where name = '店铺';

店铺查账是否到账

select * from user;		-- by 店铺

但是小明这时候选择rollback

rollback;			-- by 小明

此时店铺主人重新查账

select * from user;		-- by 店铺
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |   900 |
|  2 | b    |  1100 |
|  3 | 小明 |  1000 |
|  4 | 店铺 |  1000 |
+----+------+-------+
4 rows in set (0.00 sec)

这里店铺和小明开启了两个不同的事务B和A,如果事务A(小明)开启之后,他的未提交数据可以被其他(店铺)用户读取,这样就会出现脏读,开发中不允许出现脏读

2. read committed 读已提交的 可能会出现不可重复读现象

先是修改隔离级别,类似上面的

小张

start transaction;
select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |   900 |
|  2 | b    |  1100 |
|  3 | 小明 |  1000 |
|  4 | 店铺 |  1000 |
+----+------+-------+

小王

start transaction;
insert into user values(5,'c',100);
commit;

小张

select avg(money) from user;
+------------+
| avg(money) |
+------------+
|   820.0000 |

这里小张看到平均值不是之前自己看到的,之前是1000。

虽然只能读到提交的数据,但是读取同一张的数据可能前后不一致(两个人操作)。

这也叫做不可重复读现象

3. repeatable read (默认隔离级别) 重复读 可能出现幻读

修改隔离级别和前面类似

张三:

start transaction;

王五:

start transaction; 

张三:

insert into user values(6,'d',1000);
commit;

王五:

insert into user values(6,'d',1000);

张三在提交之后,王五那边不能够即使相似,当王五也插入6号数据的时候,就会报错,因为数据已经存在,但是因为repeatable read的隔离王五看不到。这就叫做幻读

事务A和事务B同时操作一张表,事务A提交的数据也不能被事务B读到,可能造成幻读

4. serializable 串行化

张三:

start transaction;

王五:

start transaction; 

张三:

insert into user values(7,'e',1000);
commit;

王五:

start transaction;
select * from user;
-- 能看到7号用户已经存在

张三:

start transaction;
insert into user values(8,'f',1000);
-- 语句会被卡住

**当数据表被另外的事务操作的时候,其他事务里面的写操作是不可以操作,或者说会进入排队等待,**直到其他事务结束的时候,要在没有等待超时的情况下。

他的问题在于性能最低

四种隔离级别的性能排列

READ-UNCOMMITTED > READ-COMMITTED > REPEATABLE-READ > SERIALIZABLE

隔离级别越高,问题越少,但是性能越差

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值