mysql事务

–mysql事务.sql

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

比如
update user set money=money-100 where name=‘a’;
update user set money=money+100 where name=‘b’;
这两条语句必须同时成功或者失败
create table user(
id int,
name varchar(20),
money int
);

insert into user values(1,‘a’,1000);
insert into user values(2,‘b’,1000);

mysql中如何控制事务
1.mysql默认是开启事务的(自动提交)
mysql> select @@autocommit;
±-------------+
| @@autocommit |
±-------------+
| 1 |
±-------------+
1 row in set (0.00 sec)

默认事务的作用是,当执行一个sql语句时,效果会立即生效,且不能回滚。

–事务回滚:撤销sql语句执行效果

-如果想设置回滚,则设置mysql自动提交为 false
set autocommit=0;

–设置完成之后,操作完成之后,如果不想再次被回滚了,再加一条commit语句
commit 手动提交数据

–自动提交:@@autocommit=1
–手动提交:commit;
–回滚:rollback;
实际开发中,事务给我们提供了一个反悔机会

begin;或者 start transaction;都可以开启一个事务
–手动开启事务,可以rollback
–事务一旦开启,一旦commit,就不可以回滚了

–事务的四大特征:
A 原子性:事务是最小的单位,不可再分隔
C 一致性:事务要求,在同一事务中的sql语句,必须保证同时成功或者同时失败
I 隔离性:事务一和事务二之间是有隔离性的
D 持久性:事务一旦结束(commit,rollback),就不可以返回。

–事务开启
1.修改默认提交 set autocommit=0;
2.begin
3.start transaction

–事务手动提交
commit

–事务手动回滚
rollback

–事务的隔离性
1.read uncommitted; 读未提交的
2.read committed; 读已经提交的
3.repeatable read 可以重复读
4.serializable; 串行化

1.1 read uncommitted;
如果有事务a和事务b
a事务对数据进行操作,在操作的过程中,事务没有被提交,但是b可以看见a操作的结果

insert into user values(3,‘小明’,1000);
insert into user values(4,‘淘宝店’,1000);

–如何查询数据库的隔离级别
mysql 8.0
select @@global.transaction_isolation;–系统级别
select @@transaction_isolation; --会话级别的

mysql 5.x
select @@global.tx_isolation;
select @@tx_isolation;

–如何修改隔离级别
set global transaction isolation level read uncommitted;

如果两个不同的地方,都在进行操作,如果事务a开启之后,他的数据可以被其他事务读取到
就会出现脏读
脏读:一个事务读到了另外一个事务的没有提交的数据,就叫做脏读,
实际开发是不允许脏读出现的,防止被别人回滚。

2.read committed 读已经提交的
set global transaction isolation level read committed;

举个生动的例子:
小王是银行的会计,他做了一张表
start transaction;
select * from user;

小张是一个坏人,他趁小王不注意,在另一个终端,插入了一条数据
start transaction;
insert into user values(5,‘小章’,100);

当小王打算计算平均值时:
select avg(money) from user;

发现平均值出现了问题,比原来变小了

–由此,虽然我只能读到另外一个事务提交的数据,但还是会出现问题,就是读取同一个表的数据,发现前后不一致
不可重复读现象:read committed;

3.repeatable read 可以重复读

set global transaction isolation level repeatable read;

–再举个栗子
张全蛋在成都开启了个事务:
start transaction;

王尼玛在北京开启了个事务:
start transaction;

张全蛋插入了一条数据:
insert into user values(6,‘d’,1000);
commit;

–王尼玛也想插入一条数据,但是他不知道张全蛋添加了这条数据,当他查询表时,并没有发现张全蛋插入的这条数据,这时候王尼玛插入了相同的一条数据,数据库会报错,显示这条数据已经显示,王尼玛很懵逼,因为他查询整个表并没有这条数据。

那么这种现象就叫做幻读,
事务a和事务b,同时操作一张表,事务a提交的数据,也不能被b读到,就会造成幻读。

4.serializable 串行化
set global transaction isolation level serializable;
还是用上面的例子
张全蛋在成都开启了个事务:
start transaction;

王尼玛在北京开启了个事务:
start transaction;

张全蛋在成都添加了一条数据:
insert into user values(7,‘波澜哥’,1000);
commit;
select * from user;

王尼玛在北京查询这个表:
select * from user;
发现了张全蛋添加的那条数据

张全蛋在成都再插入一条数据
start transaction;
insert into user values(8,‘建国’,1000);
当输入这条语句之后你会发现终端会卡在这里,下面是空的,你可以自己操作体验一下

一直到王尼玛输入 commit 提交之后,张全蛋这才可以进行写入操作

–当user表被另一个事务操作的时候,其他事务里面的写操作是不可以进行的。
–进入排队状态(串行化),直到提交之后,才可以写
–前提是在没有等待超时的情况下

但是串行化有问题,就是性能特差
read uncommitted>read commit>repeatable read>serializable
–隔离级别越高。性能越差

mysql默认隔离级别是 repeatable read

你可能感兴趣的:(数据库)