在服务开发中使用数据库锁

举报
码乐 发表于 2025/02/05 10:20:14 2025/02/05
【摘要】 1 简介数据库锁 (Database Lock) 是对整个数据库的加锁。这种锁通常用于保护数据库级别的操作,例如更改数据库结构或进行备份。它的用途是数据库锁通常较少,但它可以用于确保在某些情况下,整个数据库在事务操作中是原子性的。 2 数据库锁(Database Lock) 设计模式(1) 什么是数据库锁?数据库锁(Database Lock)是对整个数据库加锁,以防止其他会话对该数据库执...

1 简介

数据库锁 (Database Lock) 是对整个数据库的加锁。这种锁通常用于保护数据库级别的操作,例如更改数据库结构或进行备份。

它的用途是数据库锁通常较少,但它可以用于确保在某些情况下,整个数据库在事务操作中是原子性的。

2 数据库锁(Database Lock) 设计模式

(1) 什么是数据库锁?

数据库锁(Database Lock)是对整个数据库加锁,以防止其他会话对该数据库执行写入或修改操作。数据库锁的主要作用是确保数据库级别的操作的完整性和一致性。

(2) 数据库锁 vs. 全局锁

  对比项 			数据库锁(Database Lock) 			全局锁(Global Lock)
  作用范围    	单个数据库   							整个 MySQL 实例
  锁定方式    	LOCK DATABASES(不支持,需通过方案实现)  FLUSH TABLES WITH READ LOCK
  影响  		 仅影响一个数据库,其他数据库可正常读写    所有数据库的写操作都会被阻塞
  使用场景    结构变更、数据库级备份、批量数据操作     全量备份、数据库迁移
  
	影响SQL操作  CREATE TABLE、DROP TABLE、
    			ALTER TABLE、INSERT/UPDATE/DELETE    	所有写操作

MySQL 本身没有提供直接的 LOCK DATABASE 语法,但可以通过以下方式模拟数据库锁:

使用 FLUSH TABLES WITH READ LOCK(影响所有数据库,不是单独的数据库锁)。
使用 LOCK TABLES … WRITE(锁住特定数据库的所有表)。
使用 SET GLOBAL read_only = ON(将 MySQL 设为只读)。

利用事务级锁(适用于 InnoDB 引擎)。

3. 数据库锁的使用场景

(1) 备份单个数据库
需要保证备份过程中该数据库的数据不会被修改,可以先加锁,然后执行 mysqldump 备份。

(2) 数据库结构变更
当要执行 DROP DATABASE 或 ALTER TABLE 等操作时,可以锁住数据库,防止其他用户并发修改。

(3) 批量数据导入
在大批量数据插入前,可以加数据库锁,防止读取未完成数据导致不一致问题。

4 MySQL 数据库锁的实现方式

由于 MySQL 没有 LOCK DATABASE 语法,我们可以使用以下方法实现数据库级锁。

方法 1:锁住数据库所有表(模拟数据库锁)

– 锁定某个数据库的所有表

    USE mydatabase;
    FLUSH TABLES WITH READ LOCK;

– 现在可以进行备份或其他操作

– 例如:mysqldump -u root -p mydatabase > backup.sql

– 释放锁

            UNLOCK TABLES;

解释:

    FLUSH TABLES WITH READ LOCK; 锁住所有表,防止写入操作。
    mysqldump 备份数据库数据。
    UNLOCK TABLES; 释放锁,使数据库恢复正常使用。

方法 2:将数据库设为只读

– 让整个数据库实例进入只读模式

		SET GLOBAL read_only = ON;

– 进行数据库操作

– 释放锁,使数据库可写

        SET GLOBAL read_only = OFF;

解释:

    SET GLOBAL read_only = ON; 禁止所有写入操作(仅 SUPER 用户可以写)。
    SET GLOBAL read_only = OFF; 允许写入。

5 在web服务中使用数据库锁

我们可以在 Gin API 中提供一个锁定数据库的接口,以便在数据备份、批量导入等场景下使用。

代码示例
(1) 备份单个数据库

        var db *sql.DB

        func init() {
            var err error
            dsn := "root:password@tcp(127.0.0.1:3306)/testdb?parseTime=true"
            db, err = sql.Open("mysql", dsn)
            if err != nil {
                log.Fatal(err)
            }
            db.SetMaxOpenConns(10)
            db.SetMaxIdleConns(5)
        }

        // 备份单个数据库(使用数据库锁)
        func backupDatabase(c *gin.Context) {
            // 1. 锁定数据库所有表
            _, err := db.Exec("FLUSH TABLES WITH READ LOCK;")
            if err != nil {
                c.JSON(http.StatusInternalServerError, gin.H{"error": "无法锁定数据库"})
                return
            }

            // 2. 备份数据库
            cmd := exec.Command("sh", "-c", "mysqldump -u root -pYOUR_PASSWORD testdb > backup.sql")
            err = cmd.Run()
            if err != nil {
                // 释放锁
                db.Exec("UNLOCK TABLES;")
                c.JSON(http.StatusInternalServerError, gin.H{"error": "备份失败"})
                return
            }

            // 3. 释放数据库锁
            _, err = db.Exec("UNLOCK TABLES;")
            if err != nil {
                c.JSON(http.StatusInternalServerError, gin.H{"error": "无法解锁数据库"})
                return
            }

            c.JSON(http.StatusOK, gin.H{"message": "数据库备份成功"})
        }

        func main() {
            r := gin.Default()
            r.GET("/backup", backupDatabase)
            r.Run(":8080")
        }

6 小结 数据库锁 vs. 全局锁

主要区别对比

  对比项 			数据库锁(Database Lock) 		全局锁(Global Lock)
  作用范围    		单个数据库   					整个 MySQL 实例
  影响  				仅影响一个数据库    			影响全部,整个MySQL实例只读
  主要方式    	FLUSH TABLES WITH READ LOCK  		 FLUSH TABLES WITH READ LOCK(所有数据库)
  适用场景    备份单个数据库、数据库结构变更 			全量备份、数据库迁移
  是否影响其他数据库   否   是

数据库锁的作用

主要用于锁定单个数据库,防止修改,用于数据库备份、数据迁移、结构变更等场景。
MySQL 没有直接的 LOCK DATABASE 语法,通常通过 FLUSH TABLES WITH READ LOCK 或 SET GLOBAL read_only = ON 来模拟数据库锁。

数据库锁 vs. 全局锁

    数据库锁:影响单个数据库,其他数据库仍然可以操作。
    全局锁:影响整个 MySQL 服务器,所有数据库的写操作都会被阻塞。

API 结合数据库锁

可以在 Web 服务中提供API 触发数据库锁,确保在备份或迁移过程中数据一致。
如果你的业务场景只涉及单个数据库,可以使用数据库锁;如果涉及整个数据库实例的保护,可以使用全局锁。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。