事务

2020-11-30  本文已影响0人  爱折腾的傻小子
原子性(Atomicity)
一致性(Consistency)
隔离性(Isoladon)
持久性(Durability)

Mysql中事务操作
隐式事务
show variables like 'autocommit';
```sql
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
1 row in set, 1 warning (0.00 sec)
-- autocommit 为ON表示开启了自动提交。
显示事务
set autocommit=0;  -- 开启事务
insert into test1 values(1);  -- 插入数据
commit;  -- 提交
set autocommit=0;  -- 开启事务
insert into test1 values(2);  -- 插入数据
rollback;  -- 回滚
start transaction;  -- 开启事务
insert into test1 values (2);  -- 插入数据
insert into test1 values (3);  -- 插入数据
commit;  -- 提交
start transaction;  -- 开始事务
delete from test1;  -- 删除表
rollback;  -- 回滚

savepoint关键字
start transaction;  -- 开启事务
insert into test1 values (1); -- 插入一条数据
savepoint part1; -- 设置⼀个保存点
insert into test1 values (2);
-- 将savepint = part1的语句到当前语句之间所有的操作回滚
rollback to part1;
commit;  -- 提交

只读事务
start transaction read only;  -- 开启只读事务
select * from test1;
delete from test1; -- 只读事务中执⾏delete会报错
commit;

脏读
读已提交
可重复读
幻读

事务的隔离级别
show variables like 'transaction_isolation';
/*
+-----------------------+----------------+
| Variable_name | Value |
+-----------------------+----------------+
| transaction_isolation | READ-COMMITTED |
+-----------------------+----------------+
1 row in set, 1 warning (0.00 sec)
*/
隔离级别的设置
READ-UNCOMMITTED:读未提交
show variables like 'transaction_isolation';
/*
+-----------------------+----------------+
| Variable_name | Value |
+-----------------------+----------------+
| transaction_isolation | READ-UNCOMMITTED |
+-----------------------+----------------+
1 row in set, 1 warning (0.00 sec)
*/
-- A窗口如下:
start transaction;  -- 开启事务
select * from test1;  -- 查询
/*
Empty set (0.00 sec)
*/
select * from test1;
/*
+------+
| a |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
*/
commit;
/*
Query OK, 0 rows affected (0.00 sec)
*/
-- B窗口如下:
start transaction;  -- 开启事务
insert into test1 values (1); -- 插入
select * from test1;
/*
+------+
| a |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
*/
commit;
/*
Query OK, 0 rows affected (0.00 sec)
*/
READ-COMMITTED:读已提交
show variables like 'transaction_isolation';
/*
+-----------------------+----------------+
| Variable_name | Value |
+-----------------------+----------------+
| transaction_isolation | READ-COMMITTED |
+-----------------------+----------------+
1 row in set, 1 warning (0.00 sec)
*/
-- A窗口如下:
start transaction;  -- 开启事务
select * from test1;
/*
Empty set (0.00 sec)
*/
select * from test1;
/*
Empty set (0.00 sec)
*/
select * from test1;
/*
+------+
| a |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
*/
commit;
-- B窗口如下:
start transaction;  -- 开启事务
insert into test1 values (1); 
/*
Query OK, 1 row affected (0.00 sec)
*/
select * from test1;
/*
+------+
| a |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
*/
commit;
/*
Query OK, 0 rows affected (0.00 sec)
*/
REPEATABLE-READ:可重复读
show variables like 'transaction_isolation';
/*
+-----------------------+----------------+
| Variable_name | Value |
+-----------------------+----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+----------------+
1 row in set, 1 warning (0.00 sec)
*/
-- A窗口如下:
start transaction; -- 开启事务
select * from test1;
/*
Empty set (0.00 sec)
*/
select * from test1;
/*
Empty set (0.00 sec)
*/
commit;
/*
Query OK, 0 rows affected (0.00 sec)
*/
select * from test1;
/*
+------+
| a |
+------+
| 1 |
| 1 |
+------+
2 rows in set (0.00 sec)
*/
-- B窗口如下:
start transaction; -- 开启事务
insert into test1 values (1);
/*
Query OK, 1 row affected (0.00 sec)
*/
select * from test1;
/*
+------+
| a |
+------+
| 1 |
| 1 |
+------+
2 rows in set (0.00 sec)
*/
commit;
/*
Query OK, 0 rows affected (0.00 sec)
*/
幻读演示
show variables like 'transaction_isolation';
/*
+-----------------------+----------------+
| Variable_name | Value |
+-----------------------+----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+----------------+
1 row in set, 1 warning (0.00 sec)
*/
--  数据准备
create table t_user(
  id int primary key,
  name varchar(16) 
  unique name
);
insert into t_user values 
  (1,'路人甲Java'),
  (2,'路人甲Java');
/*
ERROR 1062 (23000): Duplicate entry '路人甲Java' for key 'name'
*/
select * from t_user;
/*
Empty set (0.00 sec)
*/
-- 上面我们创建t_user表,name添加了唯一约束,表示name不能重复,否则报错
-- A窗口如下:
start transaction;
/*
Query OK, 0 rows affected (0.00 sec)
*/
select * from t_user where name='路人甲Java';
/*
Empty set (0.00 sec)
*/
insert into t_user values (2,'路人甲Java');
/*
ERROR 1062 (23000): Duplicate entry '路人甲Java' for key 'name'
*/
commit;
/*
Query OK, 0 rows affected (0.00 sec)
*/
-- B窗口如下:
start transaction;
insert into t_user values (1,'路⼈甲Java');
/*
Query OK, 1 row affected (0.00 sec)
*/
select * from t_user;
/*
+----+---------------+
| id | name |
+----+---------------+
| 1 | 路⼈甲Java |
+----+---------------+
1 row in set (0.00 sec)
*/
commit;
/*
Query OK, 0 rows affected (0.00 sec)
*/
A想插入数据 路人甲Java ,插入之前先查询了一下(T5时刻)该用户是否存在,发现不存在,然后在T7时刻执行插入,报错了,报数据已经存在了,因为T6时刻 B 已经插入了 路人甲Java 。
然后A有点郁闷,刚才查的时候不存在的,然后A不相信自己的眼睛,又去查一次(T8时刻),发现 路人甲Java 还是不存在的。
数据明明不存在啊,为什么无法插入呢?这不是懵逼了么,A觉得如同发生了幻觉一样
SERIALIZABLE:串⾏
show variables like 'transaction_isolation';
/*
+-----------------------+--------------+
| Variable_name | Value |
+-----------------------+--------------+
| transaction_isolation | SERIALIZABLE |
+-----------------------+--------------+
1 row in set, 1 warning (0.00 sec)
*/
-- 事务只能串行执行了。串行情况下不存在脏读、不可重复读、幻读的问题了

关于隔离级别的选择

总结
上一篇 下一篇

猜你喜欢

热点阅读