Go 语言实现 MySQL 数据库事务

打印 上一主题 下一主题

主题 892|帖子 892|积分 2676

Go 实现 MySQL 数据库事务

一、MySQL事务

MySQL事务是指一组数据库操作,它们被视为一个逻辑单元,并且要么全部成功执行,要么全部回滚(撤销)。事务是数据库管理系统提供的一种机制,用于确保数据的一致性和完整性。
事务具有以下特性(通常由ACID原则定义):

  • 原子性(Atomicity):事务中的所有操作要么全部成功执行,要么全部回滚,不存在部分执行的情况。如果事务中的任何一个操作失败,则所有操作都会被回滚到事务开始之前的状态,保持数据的一致性。
  • 一致性(Consistency):事务的执行使数据库从一个一致的状态转换到另一个一致的状态。这意味着在事务开始和结束时,数据必须满足预定义的完整性约束。
  • 隔离性(Isolation):事务的执行是相互隔离的,即一个事务的操作在提交之前对其他事务是不可见的。并发事务之间的相互影响被隔离,以避免数据损坏和不一致的结果。
  • 持久性(Durability):一旦事务提交成功,其对数据库的更改将永久保存,即使在系统故障或重启之后也能保持数据的持久性。
在MySQL中,使用以下语句来开始一个事务:
  1. START TRANSACTION;
复制代码
在事务中,可以执行一系列的数据库操作,如插入、更新和删除等。最后,使用以下语句来提交事务或回滚事务:
提交事务:
  1. COMMIT;
复制代码
回滚事务:
  1. ROLLBACK;
复制代码
通过使用事务,可以确保数据库操作的一致性和完整性,尤其在处理涉及多个相关操作的复杂业务逻辑时非常有用。
二、MySQL 事务 示例

以下是一个示例,演示如何在MySQL中使用事务:
  1. START TRANSACTION;
  2. -- 在事务中执行一系列数据库操作
  3. INSERT INTO users (name, age) VALUES ('Alice', 25);
  4. UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
  5. DELETE FROM logs WHERE user_id = 1;
  6. -- 如果一切正常,提交事务
  7. COMMIT;
复制代码
在上述示例中,我们开始了一个事务,并在事务中执行了一系列数据库操作。
首先,我们向users表插入了一条新记录,
然后更新了accounts表中用户ID为1的账户余额,
最后删除了logs表中与用户ID为1相关的日志条目。
如果在事务执行的过程中出现任何错误或异常情况,可以使用ROLLBACK语句回滚事务,使所有操作都被撤销,数据库恢复到事务开始之前的状态:
  1. START TRANSACTION;
  2. -- 在事务中执行一系列数据库操作
  3. INSERT INTO users (name, age) VALUES ('Bob', 30);
  4. UPDATE accounts SET balance = balance - 200 WHERE user_id = 2;
  5. -- 发生错误或异常,回滚事务
  6. ROLLBACK;
复制代码
在上述示例中,如果在更新accounts表的操作中发生错误,整个事务将被回滚,插入的用户记录和更新的账户余额将被撤销。
事务的关键在于将多个相关的数据库操作组织在一起,并以原子性和一致性的方式进行提交或回滚。这确保了数据的完整性和一致性,同时也提供了灵活性和错误恢复机制。
三、MySQL 事务引擎

MySQL提供了多个事务引擎,每个引擎都具有不同的特性和适用场景。以下是MySQL中常见的事务引擎:

  • InnoDB:InnoDB是MySQL默认的事务引擎。它支持事务、行级锁定、外键约束和崩溃恢复等功能。InnoDB适用于需要强调数据完整性和并发性能的应用程序。
  • MyISAM:MyISAM是MySQL的另一个常见的事务引擎。它不支持事务和行级锁定,但具有较高的插入和查询性能。MyISAM适用于读密集型应用程序,例如日志记录和全文搜索。
  • NDB Cluster:NDB Cluster是MySQL的集群事务引擎,适用于需要高可用性和可扩展性的分布式应用程序。它具有自动分片、数据冗余和故障恢复等功能。
  • Memory:Memory(也称为Heap)引擎将表数据存储在内存中,提供非常高的插入和查询性能。但由于数据存储在内存中,因此在数据库重新启动时数据会丢失。Memory引擎适用于临时数据或缓存数据的存储。
除了以上列出的常见事务引擎之外,MySQL还支持其他一些事务引擎,例如Archive、Blackhole等。每个引擎都有其独特的特性和适用场景,选择合适的事务引擎需要根据应用程序的需求和性能要求进行评估。
在创建表时,可以指定所需的事务引擎。例如,使用以下语句创建一个使用InnoDB引擎的表:
  1. CREATE TABLE mytable (
  2.   id INT PRIMARY KEY,
  3.   name VARCHAR(50)
  4. ) ENGINE=InnoDB;
复制代码
需要注意的是,不同的事务引擎可能会有不同的配置和限制,因此在选择和使用特定的事务引擎时,建议参考MySQL文档以了解详细信息和最佳实践。
四、事务实例

开启事务 Begin 源码:
  1. // BeginTx starts a transaction.
  2. //
  3. // The provided context is used until the transaction is committed or rolled back.
  4. // If the context is canceled, the sql package will roll back
  5. // the transaction. Tx.Commit will return an error if the context provided to
  6. // BeginTx is canceled.
  7. //
  8. // The provided TxOptions is optional and may be nil if defaults should be used.
  9. // If a non-default isolation level is used that the driver doesn't support,
  10. // an error will be returned.
  11. func (db *DB) BeginTx(ctx context.Context, opts *TxOptions) (*Tx, error) {
  12.         var tx *Tx
  13.         var err error
  14.         err = db.retry(func(strategy connReuseStrategy) error {
  15.                 tx, err = db.begin(ctx, opts, strategy)
  16.                 return err
  17.         })
  18.         return tx, err
  19. }
  20. // Begin starts a transaction. The default isolation level is dependent on
  21. // the driver.
  22. //
  23. // Begin uses context.Background internally; to specify the context, use
  24. // BeginTx.
  25. func (db *DB) Begin() (*Tx, error) {
  26.         return db.BeginTx(context.Background(), nil)
  27. }
复制代码
中止事务 Rollback 源码:
  1. // rollback aborts the transaction and optionally forces the pool to discard
  2. // the connection.
  3. func (tx *Tx) rollback(discardConn bool) error {
  4.         if !tx.done.CompareAndSwap(false, true) {
  5.                 return ErrTxDone
  6.         }
  7.         if rollbackHook != nil {
  8.                 rollbackHook()
  9.         }
  10.         // Cancel the Tx to release any active R-closemu locks.
  11.         // This is safe to do because tx.done has already transitioned
  12.         // from 0 to 1. Hold the W-closemu lock prior to rollback
  13.         // to ensure no other connection has an active query.
  14.         tx.cancel()
  15.         tx.closemu.Lock()
  16.         tx.closemu.Unlock()
  17.         var err error
  18.         withLock(tx.dc, func() {
  19.                 err = tx.txi.Rollback()
  20.         })
  21.         if !errors.Is(err, driver.ErrBadConn) {
  22.                 tx.closePrepared()
  23.         }
  24.         if discardConn {
  25.                 err = driver.ErrBadConn
  26.         }
  27.         tx.close(err)
  28.         return err
  29. }
  30. // Rollback aborts the transaction.
  31. func (tx *Tx) Rollback() error {
  32.         return tx.rollback(false)
  33. }
复制代码
提交事务 Commit 源码:

[code]// Commit commits the transaction.func (tx *Tx) Commit() error {        // Check context first to avoid transaction leak.        // If put it behind tx.done CompareAndSwap statement, we can't ensure        // the consistency between tx.done and the real COMMIT operation.        select {        default:        case
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

惊落一身雪

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表