Mysql-事务
- 一、事务是什么?
- 二、事务的特性(ACID)
- 三、事务的开启
-
- [1. Autocommit](#1. Autocommit)
- [2. 开启事务](#2. 开启事务)
- 四、事务并发存在的问题
- 五、隔离级别
- 总结
一、事务是什么?
事务是一种机制,包含了一组SQL语句
。要么同时执行,要么同时不执行
事务是一个整体
如:事务中有10个SQL语句,1234成功5失败 -> 回滚
什么情况下使用事务 -> 如银行转账
A 1000 -> B 1000
-
A - 100
-
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 => 回滚
四、事务并发存在的问题
多个事务同时并发执行时,可能会引发一系列数据一致性问题
脏读
:读到了未提交
的数据(更新数据时)不可重复读
:前后多次读取同一个数据内容不一致
(更新数据时)幻读
:前后多次读取数据,数量的总量不一致
(插入/删除数据时)丢失更新
: 多个事务同时更新同一个数据时,后提交的事务覆盖
先提交的事务
五、隔离级别
读未提交(read uncommitted)
: 读取尚未提交的数据
不解决以上任何问题
安全性最差,性能最好读已提交(read committed)
: 读取已经提交的数据,可以解决脏读
只能读到已经提交的数据,未提交的不能读取
Oracle数据中默认的级别
安全性较差,性能较好可重复读 (Repeatable read)
: 可以解决脏读、不可重复读
一个事务执行的过程中,多次读取同一个数据,会得到相同的结果
Mysql默认的隔离级别
安全性好,性能中等串行化(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 特性(原子性、一致性、隔离性、持久性),从根本上保证了数据库操作的可靠性、一致性和并发安全性,是处理关键业务(如金融交易、订单管理、数据同步等)不可或缺的机制