文章目录

  • 前言
  • 事务(Transaction)的操作
  • 什么是事务?
  • 事务的特性
  • 事务的隔离级别
  • 事务相关的语句
  • 演示事务回滚和提交
  • 演示事务隔离级别
  • read uncommitted(读取未提交)
  • read committed(读取已提交)
  • repeateable read(可重复读)
  • serializable(序列化)



前言

数据库中的事务是指对数据库执行一批操作,这些操作最终要么全部执行成功,要么全部失败!

事务(Transaction)的操作

什么是事务?

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

 事务是逻辑的一组操作,要么执行,要么不执行。

 事务的存在是保证数据的完整性,安全性。

事务的特性

事务特性

含义

原子性(Atomicity)

一个事务中的所有操作要么全部完成,要么全部失败。事务执行后,不允许停留在中间某个状态

一致性(Consistency)

不管在任何给定的时间,并发事务有多少,事务必须保证运行结果的一致性

隔离性(Isolation)

要求事务不受其他并发事务的影响,在给定的时间内,该事务是数据库唯一运行的事物

持久性(Durability)

事务一旦提交,结果便是永久性的,即便发生宕机,仍然可以依靠事务日志完成数据的持久化

事务的隔离级别

名称

隔离级别

脏读

不可重复读

幻读

读取未提交

read uncommitted




读取已提交

read committed




可重复读

repeatable-read




串行化

serializable




  • 脏读: 一个事务读取到了另一个事务中尚未提交的数据
  • 不可重复读: 一个事务中两次读取的数据内容不一致,要求的是一个事务中多次读取时数据是一致的,这是事务update时引发的问题
  • 幻读: 一个事务中两次读取的数据的数量不一致,要求在一个事务多次读取的数据的数量是一致的,这是insert或delete时引发的问题

事务相关的语句

 DML语句,insert、update、delete

 MySQL事务默认是自动提交的!只要执行一条DML就提交一次!

 MySQL默认的隔离级别是:repeatable-read (可重复读取)

  • START TRANSACTION 开启事务(关闭mysql自动提交机制)
  • ROLLBACK 事务回滚(返回事务内执行的操作)
  • COMMIT 事务提交(提交事务内执行的操作)

演示事务回滚和提交

代码如下(示例):

-- ===========================================事务回滚===========================================
-- 开启事务
START TRANSACTION;
-- 插入数据
insert into user (username,age) values('zhangsan',18);
insert into user (username,age) values('lisi',18);
insert into user (username,age) values('wangwu',18);
-- 查询
SELECT * FROM user;
-- 事务回滚
ROLLBACK;
-- 再次查询
SELECT * FROM user;

-- ===========================================提交事务===========================================
-- 开启事务
START TRANSACTION;
-- 插入数据
insert into user (username,age) values('zhangsan',18);
insert into user (username,age) values('lisi',18);
insert into user (username,age) values('wangwu',18);
-- 查询
SELECT * FROM user;
-- 事务提交
COMMIT;
-- 再次查询
SELECT * FROM user;
-- 事务回滚
ROLLBACK;		-- 已经提交了,回滚没有作用
-- 再次查询
SELECT * FROM user;

演示事务隔离级别

 设置事务的隔离级别,开启两个客户端A和B,A进行开启事务并执行查询,B进行开启事务并DML数据

read uncommitted(读取未提交)

 也叫脏读,一个事务在处理过程中读取了另外一个事务未提交的数据。

 你都还没提交,我就读到了你刚操作的数据,万一你回滚了怎么办,你说这脏不脏。

代码如下(示例):

-- 设置事务的全局隔离级别
mysql> SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
-- 查看事务的全局隔离级别
mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| READ-UNCOMMITTED        |
+-----------------------+
1 row in set, 1 warning (0.00 sec)
-- 然后重新进入MySQL
mysql> exit;

-- ================客户端A=================
mysql> use test;
Database changed
mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)
mysql> select * from user;
Empty set (0.01 sec)

-- ================客户端B=================
mysql> use test;
Database changed
mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)
mysql> insert into user (username,age) values('zhangsan',18);
Query OK, 1 row affected (0.00 sec)

-- ================客户端A=================
mysql> select * from user;
+----+----------+------+
| id | username | age  |
+----+----------+------+
|  1 | zhangsan |   18 |
+----+----------+------+
1 row in set (0.00 sec)

-- ================客户端B=================
mysql> insert into user (username,age) values('lisi',18);
Query OK, 1 row affected (0.00 sec)
-- ================客户端A=================
mysql> select * from user;
+----+----------+------+
| id | username | age  |
+----+----------+------+
|  1 | zhangsan |   18 |
|  2 | lisi     |   18 |
+----+----------+------+
2 rows in set (0.00 sec)

read committed(读取已提交)

 事务提交的数据才能被查询得到

代码如下(示例):

mysql> set global transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)
mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| READ-COMMITTED        |
+-----------------------+
1 row in set, 1 warning (0.00 sec)
mysql> exit

-- ================客户端A=================
mysql> use test;
Database changed
mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)
mysql> select * from user;
Empty set (0.01 sec)

-- ================客户端B=================
mysql> use test;
Database changed
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into user (username,age) values('zhangsan',18);
Query OK, 1 row affected (0.00 sec)

-- ================客户端A=================
mysql> select * from user;
Empty set (0.00 sec)

-- ================客户端B=================
mysql> insert into user (username,age) values('lisi',18);
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.02 sec)

-- ================客户端A=================
mysql> select * from user;
+----+----------+------+
| id | username | age  |
+----+----------+------+
|  1 | zhangsan |   18 |
|  2 | lisi     |   18 |
+----+----------+------+
2 rows in set (0.00 sec)

repeateable read(可重复读)

 客户端A事务没有提交前,不管客户端B事务执行什么操作,客户端A事务都是原始数据,如果客户端A、B事务都提交了就能读取到相同的数据行。也就是出现幻读的现象!(就是两个都要提交才能读取到相同的数据行,虽然B提交了但A没有提交也没有用)

代码如下(示例):

mysql> set global transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)
mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ       |
+-----------------------+
1 row in set, 1 warning (0.00 sec)
mysql> exit

-- ================客户端A=================
mysql> use test;
Database changed
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user;
Empty set (0.00 sec)

-- ================客户端B=================
mysql> use test;
Database changed
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into user (username,age) values('zhangsan',18);
Query OK, 1 row affected (0.00 sec)

-- ================客户端A=================
mysql> select * from user;
Empty set (0.00 sec)

-- ================客户端B=================
mysql> insert into user (username,age) values('lisi',18);
Query OK, 1 row affected (0.00 sec)

mysql> select * from user;
+----+----------+------+
| id | username | age  |
+----+----------+------+
|  1 | zhangsan |   18 |
|  2 | lisi     |   18 |
+----+----------+------+
2 rows in set (0.00 sec)

mysql> delete from user;
Query OK, 2 rows affected (0.00 sec)

mysql> select * from user;
Empty set (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.11 sec)

mysql> insert into user (username,age) values('zhangsan',18);
Query OK, 1 row affected (0.11 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user;
+----+----------+------+
| id | username | age  |
+----+----------+------+
|  3 | zhangsan |   18 |
+----+----------+------+
1 row in set (0.00 sec)

-- ================客户端A=================
mysql> select * from user;
Empty set (0.00 sec)

serializable(序列化)

 也叫串行化,排队进行事务内的操作!

 一个事务A第一次操作完,另一个事务B进行操作就会进行等待,事务A提交后,事务B就会执行操作。

代码如下(示例):

mysql> set global transaction isolation level serializable;
Query OK, 0 rows affected (0.00 sec)

mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| SERIALIZABLE          |
+-----------------------+
1 row in set, 1 warning (0.00 sec)

mysql> exit

-- ================客户端A=================
mysql> use test;
Database changed
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user;
Empty set (0.00 sec)

-- ================客户端B=================
mysql> use test;
Database changed
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into user (username,age) values('zhangsan',18);
-- 。。。。。进入一个等待的状态,等待客户端A的事务提交后才执行

-- ================客户端A=================
mysql> commit;
Query OK, 0 rows affected (0.00 sec)

-- ================客户端B=================
mysql> insert into user (username,age) values('zhangsan',18);
Query OK, 1 row affected (25.89 sec)

-- ================客户端A=================
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from user;
-- 。。。。。进入一个等待的状态,等待客户端B的事务提交后才执行

-- ================客户端B=================
mysql> commit;
Query OK, 0 rows affected (0.10 sec)

-- ================客户端A=================
mysql> select * from user;
+----+----------+------+
| id | username | age  |
+----+----------+------+
|  1 | zhangsan |   18 |
+----+----------+------+
1 row in set (4.83 sec)

mysql 事务 关闭 mysql 事务操作_database