网盘资源共享网站,定制规划设计公司,网站宣传策略,网站页面设计方案怎么写MySQL事务#xff1a;从原理到实践
引言
在现代数据库系统中#xff0c;事务#xff08;Transaction#xff09;是确保数据一致性和完整性的核心机制。MySQL作为最流行的关系型数据库之一#xff0c;其事务处理能力直接影响着应用程序的可靠性和性能。本文将深入探讨MyS…MySQL事务从原理到实践
引言
在现代数据库系统中事务Transaction是确保数据一致性和完整性的核心机制。MySQL作为最流行的关系型数据库之一其事务处理能力直接影响着应用程序的可靠性和性能。本文将深入探讨MySQL事务的方方面面从基础概念到高级特性帮助读者全面掌握MySQL事务的知识体系。
什么是事务
事务是数据库管理系统执行过程中的一个逻辑单位由一个或多个SQL语句组成。这些语句要么全部成功执行要么全部失败回滚不会出现部分执行的情况。
事务的典型场景
考虑一个银行转账的例子
A账户向B账户转账100元需要从A账户扣除100元需要向B账户增加100元
这两个操作必须作为一个整体执行任何一步失败都应该回滚整个操作否则会造成数据不一致。
事务的ACID特性
ACID是事务必须满足的四个特性这是数据库事务正确执行的四个基本要素
1. 原子性Atomicity
事务是一个不可分割的工作单位事务中的操作要么都发生要么都不发生。MySQL通过undo log来保证事务的原子性。
2. 一致性Consistency
事务必须使数据库从一个一致性状态变换到另一个一致性状态。数据的完整性约束不能被破坏。
3. 隔离性Isolation
多个用户并发访问数据库时一个用户的事务不能被其他用户的事务所干扰。MySQL通过锁机制和MVCC多版本并发控制来实现隔离性。
4. 持久性Durability
一旦事务提交则其结果就是永久的即使系统崩溃也不会丢失。MySQL通过redo log来保证事务的持久性。
MySQL事务的使用
开启事务
-- 方式1显式开启事务
START TRANSACTION;
-- 或
BEGIN;-- 方式2关闭自动提交
SET autocommit 0;提交事务
COMMIT;回滚事务
ROLLBACK;设置保存点
-- 设置保存点
SAVEPOINT savepoint_name;-- 回滚到保存点
ROLLBACK TO savepoint_name;-- 删除保存点
RELEASE SAVEPOINT savepoint_name;完整示例
START TRANSACTION;-- 执行一些操作
UPDATE accounts SET balance balance - 100 WHERE id 1;
SAVEPOINT after_deduct;UPDATE accounts SET balance balance 100 WHERE id 2;-- 如果第二个操作失败可以回滚到保存点
-- ROLLBACK TO after_deduct;-- 如果所有操作成功提交事务
COMMIT;事务隔离级别
MySQL提供了四种事务隔离级别用于控制事务之间的隔离程度
1. READ UNCOMMITTED读未提交
最低的隔离级别允许读取尚未提交的数据变更可能导致脏读、不可重复读和幻读
2. READ COMMITTED读已提交
允许读取并发事务已经提交的数据可以避免脏读但仍可能出现不可重复读和幻读
3. REPEATABLE READ可重复读
MySQL的默认隔离级别对同一字段的多次读取结果都是一致的可以避免脏读和不可重复读在MySQL中通过MVCC机制也可以避免幻读
4. SERIALIZABLE可串行化
最高的隔离级别完全串行化的读写可以避免脏读、不可重复读和幻读但性能影响最大
设置隔离级别
-- 查看当前隔离级别
SELECT transaction_isolation;-- 设置会话级别的隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;-- 设置全局隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;并发问题详解
1. 脏读Dirty Read
一个事务读取了另一个未提交事务修改的数据。
-- 事务A
START TRANSACTION;
UPDATE users SET age 30 WHERE id 1;
-- 未提交-- 事务B
START TRANSACTION;
SELECT age FROM users WHERE id 1; -- 读到30脏读
COMMIT;-- 事务A
ROLLBACK; -- 回滚后age应该还是原值2. 不可重复读Non-Repeatable Read
一个事务内多次读取同一数据但读取结果不一致。
-- 事务A
START TRANSACTION;
SELECT age FROM users WHERE id 1; -- 读到20-- 事务B
START TRANSACTION;
UPDATE users SET age 30 WHERE id 1;
COMMIT;-- 事务A
SELECT age FROM users WHERE id 1; -- 读到30不可重复读
COMMIT;3. 幻读Phantom Read
一个事务读取了几行数据另一个并发事务插入了一些数据再次读取时会发现多了一些原本不存在的记录。
-- 事务A
START TRANSACTION;
SELECT * FROM users WHERE age 25; -- 返回2条记录-- 事务B
START TRANSACTION;
INSERT INTO users (name, age) VALUES (Tom, 28);
COMMIT;-- 事务A
SELECT * FROM users WHERE age 25; -- 返回3条记录幻读
COMMIT;MVCC多版本并发控制
MVCC是MySQL InnoDB存储引擎实现隔离级别的一种方式用于提高数据库并发性能。
MVCC的核心概念
隐藏字段 DB_TRX_ID记录创建或最后修改该记录的事务IDDB_ROLL_PTR回滚指针指向undo log记录DB_ROW_ID隐藏主键如果表没有主键 Read View读视图 事务开启时会生成数据库系统当前的一个快照记录并维护系统当前活跃的事务ID 版本链 每次更新记录时旧版本会被保存在undo log中通过回滚指针形成一个版本链
MVCC的工作原理
在READ COMMITTED和REPEATABLE READ隔离级别下SELECT操作不会加锁而是通过MVCC来实现
每个事务都有一个唯一的事务ID在读取数据时只读取事务ID小于或等于当前事务ID的数据版本对于删除操作只是标记删除不是真正删除通过这种方式读操作不会阻塞写操作写操作也不会阻塞读操作
锁机制
MySQL使用锁机制来控制并发访问主要包括
1. 共享锁S锁Shared Lock
也称为读锁多个事务可以同时获得一个资源的共享锁获得共享锁的事务只能读取数据不能修改数据
-- 添加共享锁
SELECT * FROM users WHERE id 1 LOCK IN SHARE MODE;
-- MySQL 8.0
SELECT * FROM users WHERE id 1 FOR SHARE;2. 排他锁X锁Exclusive Lock
也称为写锁一个资源只能被一个事务获得排他锁获得排他锁的事务既能读取数据又能修改数据
-- 添加排他锁
SELECT * FROM users WHERE id 1 FOR UPDATE;-- UPDATE、DELETE、INSERT会自动加排他锁
UPDATE users SET age 30 WHERE id 1;3. 意向锁Intention Lock
意向共享锁IS事务想要获得表中某几行的共享锁意向排他锁IX事务想要获得表中某几行的排他锁
4. 锁的粒度
表级锁锁定整张表行级锁锁定特定的行页级锁锁定特定的页较少使用
死锁
当两个或多个事务相互等待对方释放锁时就会产生死锁。
死锁示例
-- 事务A
START TRANSACTION;
UPDATE accounts SET balance balance - 100 WHERE id 1;
-- 等待事务B释放id2的锁
UPDATE accounts SET balance balance 100 WHERE id 2;-- 事务B
START TRANSACTION;
UPDATE accounts SET balance balance - 50 WHERE id 2;
-- 等待事务A释放id1的锁
UPDATE accounts SET balance balance 50 WHERE id 1;死锁检测与处理
死锁检测InnoDB会自动检测死锁死锁处理选择回滚代价较小的事务查看死锁信息SHOW ENGINE INNODB STATUS;
避免死锁的方法
按相同的顺序访问对象尽量缩短事务的持续时间使用较低的隔离级别合理设计索引避免扫描过多的记录
事务日志
MySQL使用两种日志来保证事务的ACID特性
1. Undo Log回滚日志
保证事务的原子性记录数据修改前的值用于事务回滚和MVCC
2. Redo Log重做日志
保证事务的持久性记录数据修改后的值用于崩溃恢复
日志的工作流程
事务开始记录undo log更新数据页在内存中记录redo log事务提交redo log刷盘
性能优化建议
1. 合理设置隔离级别
根据业务需求选择合适的隔离级别不要盲目使用最高级别。
2. 缩短事务时间
尽快提交或回滚事务避免在事务中执行耗时操作将查询操作移出事务
3. 减少锁冲突
合理设计索引避免全表扫描按相同顺序访问资源使用乐观锁代替悲观锁适用场景下
4. 批量操作
将多个小事务合并为一个大事务减少事务开销。
5. 监控和调优
-- 查看当前事务
SELECT * FROM information_schema.INNODB_TRX;-- 查看锁等待
SELECT * FROM information_schema.INNODB_LOCK_WAITS;-- 查看锁信息
SELECT * FROM information_schema.INNODB_LOCKS;最佳实践
明确事务边界清楚地知道事务的开始和结束处理异常确保异常情况下事务能够正确回滚避免长事务长事务会占用大量资源并增加锁冲突读写分离将读操作分离到从库减少主库压力使用连接池避免频繁创建和销毁连接定期监控监控事务执行情况和锁等待情况
总结
MySQL事务是保证数据一致性和完整性的重要机制。理解事务的ACID特性、隔离级别、MVCC机制和锁机制对于开发高性能、高可靠的数据库应用至关重要。在实际应用中需要根据业务场景权衡性能和一致性选择合适的隔离级别和锁策略并持续监控和优化事务的执行效率。