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

相关推荐
宋大水1 小时前
【大作业-12】草莓成熟度检测模型,YOLO+PyQt+MySQL
数据库·深度学习·mysql·yolo·目标检测·pyqt·课程设计
_代号0071 小时前
MySQL梳理四:事务日志机制和多版本并发控制(MVCC)
mysql
赵_|大人2 小时前
Qt 自动无法加载数据库为空
开发语言·数据库·qt
sukalot2 小时前
window显示驱动开发—将加密会话与 DirectX 视频加速器 2.0 解码器配合使用
数据库·驱动开发·音视频
笑衬人心。2 小时前
MySQL 如何优化慢查询
数据库·mysql
茉莉玫瑰花茶2 小时前
MySQL内外连接详解
数据库·mysql
码明2 小时前
43.MySQL管理
数据库·sql·mysql
春时似衿里3 小时前
【Navicat 连接MySQL时出现错误1251:客户端不支持服务器请求的身份验证协议;请考虑升级MySQL客户端】
服务器·数据库·mysql
帅帅梓3 小时前
Linux lvm逻辑卷管理
linux·运维·数据库