指一组sq语句
用于关系数据库的,避免发生意外时数据的不一致
特点:Atomicity(原子性)、Consistency(一致性)、Isolation(隔离性)、Durability(持久性)
创建事务
USE sql_store;START TRANSACTION;-- ①INSERT INTO orders(customer_id,order_date,status)VALUES (2,'2022-1-1',2);-- ②INSERT INTO order_itemsVALUES (last_insert_id(),3,3,3);COMMIT;
如果①执行了但中途断开链接了,②还没执行,则①同样也不会执行
提交COMMIT:将未储存的sql语句结果写入数据库
回退ROLLBACK:撤销指定sql语句,例如INSERT,UPDATE,DELETE语句
并发和锁定
并发:多个用户同时访问处理数据库
锁定:用户A执行了事务中的代码但还未执行到提交时,用户B若同时处理这个数据,当执行到处理代码时,会一直转圈最后加载超时,因为此时该数据正在被A执行,已被锁定,当A执行COMMIT代码后,B才可以继续执行
默认情况下,MYSQL会对同时处理的数据上锁
并发问题和隔离级别

MySQL默认的隔离级别为REPEATABLE READ
越往下隔离级别越高,发生并发问题越少,但同时需要更多的锁,需要更多的资源,可能会损伤性能和扩展性
查看和更改隔离级别

SESSION表示未来的事务都采用这个隔离级别,若没有SESSION则表示下一个采用这个隔离级别
READ UNCOMMITTED读取未提交隔离级别
初始情况
用户A执行到commit语句之前时
USE sql_store;START TRANSACTION;UPDATE customersSET points = 30WHERE customer_id = 1;COMMIT;
用户B查询结果为
但A此时查询的结果为
两者不一致,出现脏读(Dirty Reads)并发问题!
READ COMMITTED读已提交隔离级别
这一隔离级别不存在脏读,但存在不可重复读
USE sql_store;SET TRANSACTION ISOLATION LEVEL READ COMMITTED;START transaction;SELECT points FROM customers WHERE customer_id = 1;SELECT points FROM customers WHERE customer_id = 1;COMMIT;
A执行第四行代码时
points = 20
B执行并提交points = 30 的事务
A继续·执行第五行代码时
points = 30
两者不一致
REPEATABLE READ 可重复读隔离级别
这能解决数据不一致问题
USE sql_store;SET TRANSACTION ISOLATION LEVEL repeatable read;START transaction;SELECT points FROM customers WHERE customer_id = 1;SELECT points FROM customers WHERE customer_id = 1;COMMIT;
A执行第四行代码
此时显示points = 40
B执行并提交points· = 50 的事务
A再执行第五行代码
但依旧显示points= 40而不是 50
但这个还有个问题,幻读,即可能漏掉或多出某部分数据
SERIALIZABLE序列化隔离级别
所有事务按照先后顺序进行,下一个事务需要等待(转圈)上一个事务结束才能执行,就像单用户系统,解决所有的并发问题
用户越多,发生在同时的请求越多,就需要更漫长的等待
Deadlock死锁
USE sql_store;START TRANSACTION ;UPDATE customers SET state = 'VA' WHERE customer_id = 3;UPDATE orders SET status = 1 WHERE order_id = 2;commit;
USE sql_store;START TRANSACTION ;UPDATE orders SET status = 1 WHERE order_id = 2;UPDATE customers SET state = 'VA' WHERE customer_id = 3;commit;
A按照顺序运行1123行代码,B运行1233行代码,第四行是进入等待,A再运行第四行代码,又进入等待,出现死锁
注意
- 事务里语句的顺序,在更新多条记录的时候,应遵循相同的顺序,顺序相反的话很有可能出现死锁
- 简化事务,缩小事务运行时长
- 当表很大时,事务可能需要很长的时间来运行,就会有冲突的风险,此时可以将事务安排在非高峰时段运行,避开大量活跃用户
