MySQL索引和事务

目录

一、MySQL 索引核心知识剖析

(一)索引的本质与概念基石

(二)索引的关键作用与显著优势

(三)索引的多元分类与特性解析

(四)创建索引的科学原则与实用依据

(五)索引的删除操作与性能优化

二、MySQL 事务深度探索

(一)事务的基础概念与应用场景

(二)事务的 ACID 原则详解

(三)事务控制语句详解

(四)事务处理方法实例解析


一、MySQL 索引核心知识剖析

(一)索引的本质与概念基石

在数据库的庞大体系中,索引扮演着至关重要的角色,它是一种精心设计的数据结构,如同图书馆中详细分类的书籍目录,能够极大地提升数据检索的效率。从本质上讲,索引是一个有序排列的列表,在这个列表里,不仅存储着索引值,还记录了包含该值的数据所在行的物理地址。这一特性使得在数据量极为庞大的情况下,数据库系统无需逐行扫描全表来定位目标数据,而是借助索引表快速获取数据的物理地址,进而精准访问所需数据,大幅减少了数据查询的时间开销。

从数据存储的底层视角来看,当数据存储在磁盘等存储介质上时,是以数据块的形式存在的。这些数据块类似链表结构,每个数据块包含数据部分以及一个指向下一个数据块的指针,这种结构允许数据块在磁盘上非连续存储,保证了数据操作的原子性。在进行数据检索时,如果在无序字段上进行搜索,就需要执行线性搜索。假设数据表占据的数据块数目为 N,那么平均需要访问 N/2 个数据块才能找到目标数据;若搜索的是非主键字段,由于该字段不具备唯一的访问入口,就需要遍历 N 个数据块来搜索整个表格空间,这种方式在数据量较大时效率极低。而对于有序字段,数据库系统可以运用二分查找算法,仅需访问 log₂(N) 个数据块就能完成搜索,这就是索引能够显著提升数据表性能的根本原因。索引通过对记录集的多个字段进行排序,构建出一个新的数据结构,该结构包含字段数值以及指向相关记录的指针,随后对这个索引结构进行排序,从而实现高效的二分查找。

(二)索引的关键作用与显著优势

  1. 单表查询的加速引擎:在索引列上,数据库系统利用多种先进的快速定位技术,能够极大地提升查询效率。尤其是当数据表中的数据量达到海量级别时,索引对查询速度的提升效果更为显著。以一个包含大量用户信息的用户表为例,若要查询年龄大于 30 岁的用户记录,在未建立索引的情况下,数据库需要逐行扫描整个表来筛选符合条件的数据;而在为年龄字段建立索引后,数据库可以借助索引快速定位到满足条件的记录,查询速度将得到大幅提升。
  2. 多表连接查询的性能优化器:在涉及多个表的复杂查询场景中,索引的作用更加凸显。假设有三个未建立索引的表 t1、t2、t3,每个表都包含 1000 行数据,且数据范围为 1 - 1000。执行 “SELECT c1, c2, c3 FROM t1, t2, t3 WHERE c1=c2 AND c1=c3;” 这样的查询时,在无索引的情况下,数据库需要遍历三个表的所有数据组合,即 1000×1000×1000(十亿)种组合,才能找到符合 WHERE 子句条件的行,查询过程极其耗时。而当为每个表的相关字段建立索引后,查询过程将发生显著变化。首先,从表 t1 中选择第一行数据,查看该行所包含的数据;然后,利用表 t2 上的索引,能够直接定位到 t2 中与 t1 的值匹配的行;同理,借助表 t3 上的索引,也可以直接定位到 t3 中与 t1 的值匹配的行。接着,扫描表 t1 的下一行并重复上述过程,直至遍历完 t1 中的所有行。在这种情况下,虽然仍需对表 t1 进行完全扫描,但在表 t2 和 t3 上能够通过索引查找直接获取匹配的行,相比未使用索引时,查询速度可提升一百万倍。由此可见,索引不仅加速了 WHERE 子句满足条件行的搜索,还在多表连接查询时加快了与其他表中的行匹配的速度,极大地优化了查询性能。

(三)索引的多元分类与特性解析

  1. 基于物理存储的分类
    • 聚簇索引:聚簇索引是按照数据存放的物理位置进行排序的索引类型。它的特点是将数据与索引紧密结合,数据行的物理存储顺序与索引键值的顺序一致。这使得在进行多行检索时,聚簇索引能够充分利用数据的物理连续性,减少磁盘 I/O 操作,从而显著提高查询效率。例如,在一个按时间顺序存储的日志表中,若以时间字段建立聚簇索引,当查询某个时间段内的日志记录时,聚簇索引可以快速定位到相应的数据块,直接获取所需数据,避免了大量的数据扫描操作。
    • 非聚簇索引:与聚簇索引不同,非聚簇索引的数据存储顺序与索引键值的顺序相互独立。非聚簇索引在存储时,除了索引键值外,还包含一个指向数据行的指针。这种结构使得非聚簇索引在单行检索场景下表现出色,因为它可以通过索引快速定位到指针,进而直接访问目标数据行,无需扫描大量的数据块。比如,在一个用户信息表中,若以用户 ID 建立非聚簇索引,当查询特定用户 ID 的记录时,非聚簇索引能够迅速定位到对应的指针,直接获取该用户的详细信息,查询速度极快。
  2. 基于逻辑层面的分类
    • 普通索引:普通索引是最基本、最常用的索引类型,它对索引列的值没有任何特殊限制。在大多数情况下,当需要提升查询效率时,首先考虑创建普通索引。普通索引的创建方式灵活多样,主要有以下几种:
      • 直接创建索引:使用 “CREATE INDEX index_name ON table_name (column (length));” 语句可以直接创建普通索引。其中,column 指定要创建索引的列名,通常建议选择在 JOIN 子句和 WHERE 子句中频繁出现的列作为索引列,这样可以最大程度地发挥索引的作用。length 是一个可选参数,如果忽略该参数的值,则默认使用整个列的值作为索引;如果指定使用列前的 length 个字符来创建索引,即使用列的一部分来创建索引,这样做的好处是可以减小索引文件的大小,节省磁盘空间。需要注意的是,索引列的长度存在一定的限制,MyISAM 和 InnoDB 表的最大上限分别为 1000 个字节和 255 个字节。如果索引列的长度超过了这个上限,就只能使用列的前缀进行索引。此外,对于 BLOB 或 TEXT 类型的列,由于其数据量较大,也必须使用前缀索引。例如,若要为文章表中的标题字段创建普通索引,可以执行 “CREATE INDEX title_index ON articles (title (100));”,表示使用标题字段的前 100 个字符创建索引。
      • 修改表结构添加索引:通过 “ALTER TABLE table_name ADD INDEX index_name (column (length));” 语句,可以在已存在的表结构上添加普通索引。这种方式适用于在表创建之后,根据实际业务需求新增索引的场景。比如,在一个已经存在的用户表中,若后续发现经常需要根据用户的邮箱地址进行查询,就可以执行 “ALTER TABLE users ADD INDEX email_index (email);” 来为邮箱字段添加普通索引。
      • 创建表结构时同时创建索引:在使用 CREATE TABLE 语句创建表结构时,可以直接在表定义中添加普通索引。例如,“CREATE TABLE products (id INT NOT NULL AUTO_INCREMENT, name VARCHAR (255) NOT NULL, price DECIMAL (10, 2) NOT NULL, PRIMARY KEY (id), INDEX name_index (name));”,在创建 products 表的同时,为 name 字段创建了名为 name_index 的普通索引。
    • 唯一索引:唯一索引是一种特殊的普通索引,它除了具备普通索引的功能外,还确保索引列的值在表中是唯一的,不允许出现重复值。这一特性在保证数据的唯一性和完整性方面具有重要作用。例如,在用户表中,用户的身份证号码字段通常需要创建唯一索引,以防止出现重复的身份证号码。创建唯一索引的语句为 “CREATE UNIQUE INDEX index_name ON table_name (column (length));”,也可以在修改表结构或创建表时添加唯一索引。如 “CREATE TABLE users (id INT NOT NULL AUTO_INCREMENT, id_card VARCHAR (18) NOT NULL, name VARCHAR (50) NOT NULL, PRIMARY KEY (id), UNIQUE INDEX id_card_index (id_card));”,在创建 users 表时,为 id_card 字段创建了唯一索引。
    • 主键索引:主键索引是一种特殊的唯一索引,每个表只能有一个主键索引。主键索引的主要作用是唯一标识表中的每一行数据,其值不能为空且必须唯一。在创建表时,通常会将具有唯一性和非空约束的字段定义为主键索引。例如,“CREATE TABLE orders (order_id INT NOT NULL AUTO_INCREMENT, customer_id INT NOT NULL, order_date DATE NOT NULL, PRIMARY KEY (order_id));”,在创建 orders 表时,将 order_id 字段定义为主键索引,确保每个订单都有唯一的标识。
    • 组合索引(最左前缀):在实际的数据库应用中,查询条件往往较为复杂,涉及多个字段。为了进一步提高查询效率,就需要考虑建立组合索引。组合索引是将多个字段组合在一起创建的索引,它可以覆盖多个查询条件,减少数据库的扫描次数。在创建组合索引时,需要遵循最左前缀原则。以一个 user 用户表为例,表中包含 name、age、sex 三个字段。如果分别为这三个字段建立单列普通索引,在执行 “select * from user where name='' AND age='' AND sex= ;” 这样的查询时,数据库会分别检索三条索引,虽然扫描效率有所提升,但仍未达到最优。此时,可以使用组合索引来优化查询性能。创建组合索引的语句为 “create table user (name varchar (9), age int (3), sex tinyint (1), index user (name, age, sex));”。在使用组合索引进行查询时,查询条件中的字段顺序必须与组合索引中定义的顺序一致,否则索引将不会生效。例如,“select * from user where age='' AND name='' AND sex= ;” 这样的查询方式,由于字段顺序与组合索引不一致,该组合索引将无法发挥作用。因此,在建立组合索引时,需要充分考虑实际的查询业务需求,合理安排字段顺序,以确保索引能够被有效利用。
    • 全文索引(FULLTEXT):MySQL 从 3.23.23 版开始支持全文索引和全文检索功能。在 MySQL 5.6 版本以前,FULLTEXT 索引仅可用于 MyISAM 表;在 5.6 之后,InnoDB 引擎也开始支持 FULLTEXT 索引。全文索引主要用于在 CHAR、VARCHAR 或 TEXT 类型的列中进行全文搜索,能够快速定位包含特定关键词的文本内容。对于较大的数据集,先将资料输入一个没有 FULLTEXT 索引的表中,然后再创建索引,其速度比把资料输入现有 FULLTEXT 索引的表中更快。但需要注意的是,生成全文索引是一个非常消耗时间和硬盘空间的操作,因此在使用时需要谨慎考虑。创建全文索引的方式有多种,具体如下:
      • 创建表时添加全文索引:在 CREATE TABLE 语句中直接定义全文索引,例如 “CREATE TABLE articles (id INT NOT NULL AUTO_INCREMENT, title CHAR (255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, content TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NULL, time INT (10) NULL DEFAULT NULL, PRIMARY KEY (id), FULLTEXT (content));”,在创建 articles 表时,为 content 字段创建了全文索引。
      • 修改表结构添加全文索引:使用 “mysql>ALTER TABLE article ADD FULLTEXT index_content (content);” 语句,可以在已存在的表中为指定字段添加全文索引。
      • 直接创建索引:通过 “mysql>CREATE FULLTEXT INDEX index_content ON article (content);” 语句,也可以直接为指定表的字段创建全文索引。

(四)创建索引的科学原则与实用依据

  1. 明确操作类型:在决定是否为表创建索引以及创建何种类型的索引之前,首先需要明确该表的主要操作类型。如果表的操作以大量的查询操作为主,那么创建适当的索引可以显著提升查询性能;反之,如果表的操作主要是频繁的增删改操作,过多的索引可能会导致性能下降,因为每次数据的插入、更新或删除操作都需要同时更新相应的索引,增加了数据库的额外开销。例如,在一个日志记录表中,主要操作是插入新的日志记录,查询操作相对较少,此时就不适合创建过多的索引;而在一个商品信息查询表中,主要用于根据各种条件查询商品信息,创建合适的索引则可以大大提高查询效率。
  2. 基于查询需求建索引:仔细分析 SQL 查询语句,找出那些频繁出现在 where 子句中的字段,为这些字段建立索引可以有效加快查询速度。例如,在一个电商订单表中,经常需要根据订单状态和下单时间进行查询,如 “SELECT * FROM orders WHERE order_status = 'completed' AND order_time> '2023 - 01 - 01';”,此时可以考虑为 order_status 和 order_time 字段建立索引,以提高查询性能。
  3. 合理使用复合索引:对于复杂的查询场景,当单个索引无法满足需求时,可以尝试建立复合索引。复合索引可以将多个字段组合在一起,覆盖多个查询条件,从而减少数据库的扫描次数。但需要注意的是,修改复合索引所消耗的时间比单个索引更长,因此在创建复合索引时,需要充分考虑实际的查询业务,确保索引的字段顺序合理,避免出现虽然创建了索引但无法使用的情况。例如,在一个多条件查询的用户信息表中,如果经常需要根据用户的姓名、年龄和性别进行查询,可以创建一个包含这三个字段的复合索引 “CREATE INDEX user_info_index ON users (name, age, sex);”,并在查询时按照复合索引的字段顺序编写查询条件,以充分利用索引的优势。
  4. 查看索引信息辅助决策:使用 “mysql> show index from renyuan\G” 命令可以详细查看表的索引信息,这些信息对于评估索引的有效性和进行索引优化非常有帮助。各字段的含义如下:
    • Table:表示当前查看索引信息的表名。
    • Non_unique:如果索引不能包括重复词,则该值为 0;如果可以包括重复词,则为 1。例如,普通索引的 Non_unique 值通常为 1,而唯一索引和主键索引的 Non_unique 值为 0。
    • Key_name:索引的名称,用于在数据库中唯一标识该索引。
    • Seq_in_index:索引中的列序号,从 1 开始。在复合索引中,该字段表示每个列在索引中的顺序。
    • Column_name:索引所关联的列名。
    • Collation:列以什么方式存储在索引中。在 MySQL 中,有值 'A'(表示升序)或 NULL(表示无分类)。
    • Cardinality:索引中唯一值数目的估计值。通过运行 ANALYZE TABLE 或 myisamchk -a 命令可以更新该值。基数越大,说明索引中唯一值的数量越多,当进行联合查询时,MySQL 使用该索引的机会就越大。
    • Sub_part:如果列只是被部分地编入索引,则该字段显示被编入索引的字符的数目;如果整列被编入索引,则为 NULL。例如,当使用列的前缀创建索引时,Sub_part 会显示具体的前缀长度。
    • Packed:指示关键字如何被压缩。如果没有被压缩,则该字段为 NULL。
    • Null:如果列含有 NULL 值,则该字段为 YES;如果没有,则为 NO。
    • Index_type:显示使用的索引方法,常见的有 BTREE、FULLTEXT、HASH、RTREE 等。不同的索引类型适用于不同的场景,例如 BTREE 索引适用于范围查询和排序操作,FULLTEXT 索引适用于全文搜索,HASH 索引适用于等值查询等。
    • Comment:备注信息,用于记录关于该索引的一些额外说明。

(五)索引的删除操作与性能优化

索引在创建之后会占用一定的磁盘空间,随着数据库的不断发展和业务需求的变化,表内可能会出现一些不再使用的索引。从数据库性能的角度考虑,及时删除这些无用索引是非常必要的。索引的删除操作有以下两种常用方法:

  1. 使用 DROP INDEX 语句:“DROP INDEX 索引名 ON 表名;”,该语句可以直接删除指定表的指定索引。例如,要删除 employee 表中的 name_index 索引,可以执行 “mysql> drop index name_index on employee;”,执行该语句后,指定的索引将被删除,相应的磁盘空间也会被释放。
  2. 使用 ALTER TABLE 语句:“ALTER TABLE 表名 DROP INDEX 索引名;”,通过这种方式也可以删除表中的索引。例如,“mysql> alter table renyuan drop index age_index;”,此语句将删除 renyuan 表中的 age_index 索引。

二、MySQL 事务深度探索

(一)事务的基础概念与应用场景

在 MySQL 数据库系统中,事务是一种用于处理操作量大、复杂度高的数据的机制。它将一系列相关的数据库操作组合成一个逻辑单元,这些操作要么全部成功执行,要么全部失败回滚,保证了数据的一致性和完整性。例如,在一个人员管理系统中,当删除一个人员时,不仅需要删除该人员的基本资料,还需要同时删除与该人员相关的所有信息,如信箱、文章等。这些涉及多个数据表的操作就构成了一个事务。通过事务处理,可以确保在删除人员操作过程中,所有相关数据的一致性得到维护,避免出现部分数据删除成功而部分数据未删除的情况。

在 MySQL 中,只有使用 Innodb 数据库引擎的数据库或表才支持事务功能。这是因为 Innodb 引擎采用了先进的存储技术和日志管理机制,能够有效地保证事务的原子性、一致性、隔离性和持久性(ACID 原则),为事务处理提供了坚实的基础。事务主要用于管理 insert、update、delete 等数据修改语句,确保这些操作在复杂的数据环境中能够正确、可靠地执行。

(二)事务的 ACID 原则详解

  1. 原子性(Atomicity):原子性要求一个事务中的所有操作要么全部完成,要么全部不完成,绝不允许事务执行到一半时停止。如果在事务执行过程中发生错误,数据库会自动将事务回滚(Rollback)到事务开始前的状态,就好像这个事务从未执行过一样。例如,在一个银行转账事务中,从账户 A 向账户 B 转账 100 元,这个事务包含两个操作:从账户 A 扣除 100 元,向账户 B 增加 100 元。这两个操作必须作为一个整体执行,如果在扣除账户 A 的金额后,由于某种原因(如系统故障或网络中断)无法完成向账户 B 增加金额的操作,那么整个事务必须回滚,即恢复账户 A 的原有金额,以保证数据的一致性和完整性。在 MySQL 中,可以使用 ROLLBACK 语句来实现事务的回滚操作。例如:
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 'A';
-- 假设这里出现错误,比如网络中断导致无法继续执行下一条语句
ROLLBACK;

  1. 一致性(Consistency):一致性确保在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。这意味着写入的数据必须完全符合所有的预设规则,包括数据的精确度、关联性以及后续数据库能够自动完成预定的工作。例如,在一个订单系统中,订单的总金额必须等于订单中所有商品金额之和。当一个新订单被创建或修改时,事务必须保证这个一致性规则始终成立。如果在事务执行过程中,由于某种原因导致订单总金额与商品金额之和不一致,那么这个事务是不符合一致性要求的,必须进行回滚或修正。在实际应用中,数据库通过各种约束(如主键约束、唯一约束、外键约束等)和触发器来保证数据的一致性。例如:
-- 创建一个订单表,包含订单ID、商品ID、数量、单价和总金额字段
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    product_id INT,
    quantity INT,
    unit_price DECIMAL(10, 2),
    total_amount DECIMAL(10, 2),
    FOREIGN KEY (product_id) REFERENCES products(product_id)
);

-- 创建一个触发器,在插入或更新订单时自动计算总金额
DELIMITER //
CREATE TRIGGER calculate_total_amount
BEFORE INSERT OR UPDATE ON orders
FOR EACH ROW
BEGIN
    SET NEW.total_amount = NEW.quantity * NEW.unit_price;
END //
DELIMITER ;

  1. 隔离性(Isolation):隔离性是指数据库允许多个并发事务同时对其数据进行读写和修改的能力,同时防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
    • 读未提交(Read uncommitted):这是最低的隔离级别,在这种级别下,一个事务可以读取另一个未提交事务的数据。这种隔离级别可能会导致脏读(Dirty Read)问题,即一个事务读取到了另一个事务未提交的、可能是错误的数据。例如,事务 A 修改了一条记录但未提交,此时事务 B 读取了这条被修改但未提交的记录,如果事务 A 随后回滚了修改,那么事务 B 读取到的数据就是无效的。在 MySQL 中,可以通过以下语句设置事务隔离级别为读未提交:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
START TRANSACTION;
-- 执行事务操作
COMMIT;

  • 读提交(read committed):在该隔离级别下,一个事务只能读取已经提交的事务的数据,从而避免了脏读问题。但是,它可能会导致不可重复读(Non - Repeatable Read)问题,即同一事务内多次读取同一数据时,由于其他事务在期间对该数据进行了修改并提交,导致每次读取的结果不一致。例如,事务 A 在读取一条记录后,事务 B 修改并提交了这条记录,当事务 A 再次读取该记录时,得到的结果与第一次读取的不同。在 MySQL 中,读提交是默认的事务隔离级别,可以通过以下语句显式设置:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
-- 执行事务操作
COMMIT;

  • 可重复读(repeatable read):可重复读隔离级别保证了在同一事务内多次读取相同数据时,结果始终一致,解决了不可重复读问题。但是,它可能会出现幻读(Phantom Read)问题,即当一个事务重新读取数据时,发现多了一些原本不存在的数据(因为其他事务在期间插入了新数据并提交)。在 MySQL 的 InnoDB 引擎中,默认的隔离级别就是可重复读。通过以下语句设置事务隔离级别为可重复读:
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
-- 执行事务操作
COMMIT;

  • 串行化(Serializable):串行化是最高的隔离级别,在这种级别下,事务是串行执行的,即一个事务执行完后才会执行下一个事务,从而避免了脏读、不可重复读和幻读等所有并发问题。但是,由于事务是串行执行的,所以并发性能最低,适用于对数据一致性要求极高且并发量较低的场景。例如,在一些涉及金融交易的核心系统中,可能会采用串行化隔离级别来确保数据的准确性和一致性。在 MySQL 中,可以通过以下语句设置事务隔离级别为串行化:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
START TRANSACTION;
-- 执行事务操作
COMMIT;

  1. 持久性(Durability):持久性保证了事务处理结束后,对数据的修改是永久的,即便系统发生故障(如硬件故障、软件崩溃或停电等)也不会丢失。这是通过数据库的日志机制实现的,当一个事务提交时,数据库会将该事务对数据的修改记录到日志文件中。在系统发生故障后,数据库可以通过重放日志来恢复未完成的事务和已提交事务对数据的修改,确保数据的持久性。例如,在一个电商订单系统中,当一个订单被成功创建并提交后,即使系统在之后发生故障,该订单的信息也不会丢失,用户可以在系统恢复后正常查看和处理该订单。

(三)事务控制语句详解

  1. BEGIN 或 START TRANSACTION:这两个语句用于显式地开启一个事务。在 MySQL 中,默认情况下事务是自动提交的,即执行一条 SQL 语句后就会马上执行 COMMIT 操作。因此,要显式地开启一个事务,必须使用 BEGIN 或 START TRANSACTION 语句,或者执行 SET AUTOCOMMIT = 0 来禁止当前会话的自动提交。例如:
-- 使用BEGIN开启事务
BEGIN;
-- 或者使用START TRANSACTION开启事务
START TRANSACTION;

  1. COMMIT(或 COMMIT WORK):COMMIT 语句用于提交事务,它会使已对数据库进行的所有修改变为永久性的。一旦执行 COMMIT,事务中的所有操作就会被确认并保存到数据库中,其他事务可以看到这些修改。COMMIT 和 COMMIT WORK 是等价的。例如:
START TRANSACTION;
UPDATE products SET stock = stock - 1 WHERE product_id = 1;
COMMIT;

  1. ROLLBACK(或 ROLLBACK WORK):ROLLBACK 语句用于回滚事务,它会结束用户的事务,并撤销正在进行的所有未提交的修改。当事务执行过程中出现错误或需要放弃当前事务的操作时,可以使用 ROLLBACK 语句。ROLLBACK 和 ROLLBACK WORK 是等价的。例如:
START TRANSACTION;
DELETE FROM orders WHERE order_date < '2023 - 01 - 01';
-- 发现删除操作有误,回滚事务
ROLLBACK;

  1. SAVEPOINT identifier:SAVEPOINT 允许在事务中创建一个保存点,一个事务中可以有多个保存点。保存点用于标记事务执行过程中的某个特定位置,以便后续可以将事务回滚到该保存点,而不是回滚整个事务。例如:
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 'A';
-- 创建一个保存点
SAVEPOINT transfer_step1;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 'B';
-- 如果在后续操作中出现问题,需要回滚到保存点transfer_step1
ROLLBACK TO SAVEPOINT transfer_step1;

  1. RELEASE SAVEPOINT identifier:RELEASE SAVEPOINT 语句用于删除一个事务的保存点。当没有指定的保存点时,执行该语句会抛出一个异常。例如:
START TRANSACTION;
SAVEPOINT my_savepoint;
-- 执行一些操作
RELEASE SAVEPOINT my_savepoint;

  1. ROLLBACK TO identifier:ROLLBACK TO 语句用于把事务回滚到指定的保存点。通过指定保存点的标识符,可以将事务回滚到保存点创建时的状态,撤销从保存点之后的所有操作。例如:
START TRANSACTION;
UPDATE products SET price = price * 1.1 WHERE category = 'electronics';
SAVEPOINT price_update;
UPDATE products SET stock = stock - 5 WHERE product_id = 10;
-- 如果发现价格更新有误,回滚到price_update保存点
ROLLBACK TO price_update;

  1. SET TRANSACTION:SET TRANSACTION 语句用于设置事务的隔离级别。InnoDB 存储引擎提供了 READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE 这几种事务隔离级别。例如:
-- 设置事务隔离级别为可重复读
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
-- 执行事务操作
COMMIT;

(四)事务处理方法实例解析

  1. 使用 BEGIN、ROLLBACK、COMMIT 实现事务处理:下面以一个简单的示例来说明如何使用 BEGIN、ROLLBACK、COMMIT 来实现事务处理。假设有一个数据库 kgc,其中有一个表 kgc_transaction_test 用于存储测试数据。
-- 使用kgc数据库
USE kgc;
-- 创建kgc_transaction_test表,引擎为InnoDB以支持事务
CREATE TABLE kgc_transaction_test( id INT(5)) ENGINE = InnoDB;
-- 查看表中数据(此时表为空)
SELECT * FROM kgc_transaction_test;
-- 开始一个事务
BEGIN;
-- 向表中插入两条数据
INSERT INTO kgc_transaction_test VALUES(1);
INSERT INTO kgc_transaction_test VALUES(2);
-- 提交事务,此时数据插入成功
COMMIT;
-- 再次查看表中数据,可以看到插入的两条数据
SELECT * FROM kgc_transaction_test;
-- 开始另一个事务
BEGIN;
-- 向表中插入一条数据
INSERT INTO kgc_transaction_test VALUES(3);
-- 回滚事务,插入的数据3不会生效
ROLLBACK;
-- 查看表中数据,仍然只有之前插入的两条数据
SELECT * FROM kgc_transaction_test;

  1. 通过 SET 改变自动提交模式实现事务处理:在 MySQL 中,还可以通过 SET 语句改变自动提交模式来实现事务处理。默认情况下,自动提交模式是开启的(AUTOCOMMIT = 1),即每条 SQL 语句执行后都会自动提交。通过设置 SET AUTOCOMMIT = 0 可以禁止自动提交,从而手动控制事务的提交和回滚。例如:
-- 查看当前自动提交模式(默认值为1,即开启自动提交)
SELECT @@AUTOCOMMIT;
-- 禁止自动提交
SET AUTOCOMMIT = 0;
-- 开始一个事务(虽然没有显式使用BEGIN,但由于禁止了自动提交,后续操作属于一个事务)
UPDATE products SET stock = stock - 1 WHERE product_id = 1;
UPDATE products SET sales = sales + 1 WHERE product_id = 1;
-- 提交事务
COMMIT;
-- 开启自动提交
SET AUTOCOMMIT = 1;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值