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

相关推荐
yuyue_9991 小时前
理解 mvcc
mysql
A-刘晨阳1 小时前
从MongoDB到金仓:一次电子证照系统的平滑国产化升级实践
数据库·mongodb
瓜瓜怪兽亚1 小时前
前端基础知识---10 Node.js(三)
数据结构·数据库·node.js
掘根3 小时前
【Qt】常用控件3——显示类控件
开发语言·数据库·qt
码码哈哈爱分享3 小时前
MariaDB 与 MySQL 区别
数据库·mysql·mariadb
爱敲代码的TOM3 小时前
深入MySQL底层1-存储引擎与索引
数据库·mysql
GUIQU.3 小时前
【QT】嵌入式开发:从零开始,让硬件“活”起来的魔法之旅
java·数据库·c++·qt
sz-lcw6 小时前
MySQL知识笔记
笔记·mysql·adb
牛奶咖啡137 小时前
关系数据库MySQL的常用基础命令详解实战
数据库·mysql·本地远程连接到mysql·创建mysql用户和密码·修改mysql用户的密码·设置mysql密码的使用期限·设置和移除mysql用户的权限
ANYOLY8 小时前
Redis 面试宝典
数据库·redis·面试