Mysql-事务

Mysql-事务


一、事务是什么?

事务是一种机制,包含了一组SQL语句。要么同时执行,要么同时不执行

事务是一个整体

如:事务中有10个SQL语句,1234成功5失败 -> 回滚

什么情况下使用事务 -> 如银行转账

A 1000 -> B 1000

  1. A - 100

  2. B + 100

事务格式

sql 复制代码
Begin;
SQL 语句
SQL 语句
SQL 语句
commit;

二、事务的特性(ACID)

A - Atomicity 原子性

事务是一个不可再分割的工作单元,要么都发生,要么都不发生

C - Consistency 一致性

事务开始之前和结束之后,数据库的完整性约束没有被破坏。

转账、购物(售出,库存)

I - Isolation 隔离性

多个事务并发执行时,一个事务的执行不能被其他事务干扰。

D - Durability 持久性

事务执行完成之后(commit),数据写入磁盘,不能被回滚。


三、事务的开启

1. Autocommit

设置是否自动提交
ON : 自动提交 -> 直接将数据写入数据库,相当于每次sql执行完都会自动commit
OFF: 禁止自动提交 -> 每一次写操作都需要commit/rollback操作数据才会写入数据库

每一个SQL都会当成一个事务

查看autocommit

root@(none) 10: 57>show variables like 'autocommit';

±--------------±------+

| Variable_name | Value |

±--------------±------+

| autocommit | ON |

±--------------±------+

1 row in set (0.01 sec)

设置禁止自动提交
Autocommit=0/off

commit => 将数据写入磁盘(commit前,数据在内存)

未使用commit退出后数据丢失

设置自动提交
Autocommit=1/on

执行SQL语句时,默认会将SQL当作一个事务执行,所以autocommit=1时,会自动commit操作


2. 开启事务

如果事务中有多个SQL语句,手动开启事务

  • 开启事务
    begin/start transaction
  • 执行SQL
    SQL 语句
    SQL 语句
  • 提交事务
    commit
  • 设置回滚点
    savepoint name
  • 回滚
    rollback [name]

准备工作

CREATE TABLE info(

id INT(10) PRIMARY KEY,

name VARCHAR(40),

money DOUBLE

);
INSERT INTO info VALUES (1,'A',1000);

INSERT INTO info VALUES (2,'B',1000);

SELECT * FROM info;

测试回滚

复制代码
root@test 11: 15>begin ;
Query OK, 0 rows affected (0.00 sec)

root@test 11: 16>update info set money=money+100 where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

root@test 11: 16>SELECT * FROM info;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | A    |  1100 |
|  2 | B    |  1000 |
+----+------+-------+
2 rows in set (0.00 sec)

(回滚时会彻底撤销当前事务中所有未提交的修改,并终止事务)
root@test 11: 16>rollback;
Query OK, 0 rows affected (0.00 sec)

root@test 11: 17>SELECT * FROM info;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | A    |  1000 |
|  2 | B    |  1000 |
+----+------+-------+
2 rows in set (0.00 sec)

提交测试

复制代码
root@test 11: 19>begin;
Query OK, 0 rows affected (0.00 sec)

root@test 11: 20>update info set money=money+100 where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

root@test 11: 20>SELECT * FROM info;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | A    |  1100 |
|  2 | B    |  1000 |
+----+------+-------+
2 rows in set (0.00 sec)

root@test 11: 20>commit;
Query OK, 0 rows affected (0.00 sec)

root@test 11: 20>SELECT * FROM info;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | A    |  1100 |
|  2 | B    |  1000 |
+----+------+-------+
2 rows in set (0.00 sec)

设置回滚点

复制代码
root@test 11: 20>begin;
Query OK, 0 rows affected (0.00 sec)

root@test 11: 22>update info set money=money+100 where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

root@test 11: 22>savepoint s1;
Query OK, 0 rows affected (0.00 sec)

root@test 11: 22>SELECT * FROM info;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | A    |  1200 |
|  2 | B    |  1000 |
+----+------+-------+
2 rows in set (0.00 sec)

root@test 11: 22>update info set money=money+100 where id=2;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

root@test 11: 22>savepoint s2;
Query OK, 0 rows affected (0.00 sec)

root@test 11: 23>SELECT * FROM info;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | A    |  1200 |
|  2 | B    |  1100 |
+----+------+-------+
2 rows in set (0.00 sec)

root@test 11: 23>insert into info values(3, 'C', 1000);
Query OK, 1 row affected (0.00 sec)

root@test 11: 23>savepoint s3;
Query OK, 0 rows affected (0.00 sec)

root@test 11: 23>SELECT * FROM info;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | A    |  1200 |
|  2 | B    |  1100 |
|  3 | C    |  1000 |
+----+------+-------+
3 rows in set (0.00 sec)

root@test 11: 23>rollback to s2;
Query OK, 0 rows affected (0.00 sec)

root@test 11: 24>SELECT * FROM info;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | A    |  1200 |
|  2 | B    |  1100 |
+----+------+-------+
2 rows in set (0.00 sec)

rollback => 回滚+事务结束

rollback to point => 回滚


四、事务并发存在的问题

多个事务同时并发执行时,可能会引发一系列数据一致性问题

  1. 脏读:读到了未提交的数据(更新数据时)
  2. 不可重复读:前后多次读取同一个数据内容不一致(更新数据时)
  3. 幻读:前后多次读取数据,数量的总量不一致(插入/删除数据时)
  4. 丢失更新: 多个事务同时更新同一个数据时,后提交的事务覆盖先提交的事务

五、隔离级别

  1. 读未提交(read uncommitted): 读取尚未提交的数据
    不解决以上任何问题
    安全性最差,性能最好
  2. 读已提交(read committed): 读取已经提交的数据,可以解决脏读
    只能读到已经提交的数据,未提交的不能读取
    Oracle数据中默认的级别
    安全性较差,性能较好
  3. 可重复读 (Repeatable read): 可以解决脏读、不可重复读
    一个事务执行的过程中,多次读取同一个数据,会得到相同的结果
    Mysql默认的隔离级别
    安全性好,性能中等
  4. 串行化(Serializable): 完全避免所有的问题
    事务被一个一个串行执行
    安全性最好,性能差
脏读 不可重复读 幻读 丢失更新
read uncommitted yes yes yes yes
read committed no yes yes yes
Repeatable read no no no yes
Serializable no no no no

1.查询隔离级别

查询全局事务隔离级别

select @@global.transaction_isolation;

±-------------------------------+

| @@global.transaction_isolation |

±-------------------------------+

| REPEATABLE-READ |

±-------------------------------+
show global variables like "%isolation%";

±----------------------±----------------+

| Variable_name | Value |

±----------------------±----------------+

| transaction_isolation | REPEATABLE-READ |

±----------------------±----------------+

查询当前会话(Session)的事务隔离级别

select @@session.transaction_isolation;

±--------------------------------+

| @@session.transaction_isolation |

±--------------------------------+

| REPEATABLE-READ |

±--------------------------------+
show session variables like '%isolation';

±----------------------±----------------+

| Variable_name | Value |

±----------------------±----------------+

| transaction_isolation | REPEATABLE-READ |

±----------------------±----------------+


2.设置隔离级别

全局隔离级别仅影响新创建的会话,已存在的会话不受影响

set global transaction isolation level read uncommitted;

select @@global.transaction_isolation;

±-------------------------------+

| @@global.transaction_isolation |

±-------------------------------+

| READ-UNCOMMITTED |

±-------------------------------+
root@(none) 10: 32>set session transaction isolation level reaad uncommitted;

Query OK, 0 rows affected (0.00 sec)

root@(none) 10: 33>select @@session.transaction_isolation;

±--------------------------------+

| @@session.transaction_isolation |

±--------------------------------+

| READ-UNCOMMITTED |

±--------------------------------+


总结

事务通过ACID 特性(原子性、一致性、隔离性、持久性),从根本上保证了数据库操作的可靠性、一致性和并发安全性,是处理关键业务(如金融交易、订单管理、数据同步等)不可或缺的机制

相关推荐
Java面试题总结几秒前
MySQL EXISTS 详解:存在性判断、NOT EXISTS 与实战示例
android·数据库·mysql
cuijiecheng20184 分钟前
Little-Anti-Cheat源码分析(1)——Little-Anti-Cheat插件简介
数据库
土狗TuGou7 分钟前
SQL内功笔记 · 第5篇:SQL逻辑执行顺序
数据库·笔记·后端·sql·mysql
abcy07121313 分钟前
python Django整合postgresql实现增删改查crud
mysql
MaCa .BaKa15 分钟前
56-非遗手工艺品定制平台系统
java·vue.js·spring boot·mysql·maven·非遗手工制作平台系统·非遗制作
草莓熊Lotso15 分钟前
【LangChain】聊天模型实战:结构化输出完全指南(从原理到落地)
数据库·python·langchain·软件工程
草莓熊Lotso18 分钟前
【CMake】静态库的编译、链接与引用全解析
linux·c语言·数据库·c++·软件工程·cmake
程序猿乐锅19 分钟前
【MySQL | 第六篇】 SQL 优化
数据库·sql·mysql
j7~24 分钟前
【MYSQL】索引特性--详解
数据库·mysql·索引操作·索引的理解·mysql与磁盘·b+树与mysql
ccddsdsdfsdf9 小时前
DBeaver怎么链接mongoDB
数据库·mongodb