实例讲解MySQL中乐观锁和悲观锁

实例讲解MySQL中乐观锁和悲观锁

介绍

在多线程编程中,为了避免并发访问造成的数据不一致问题,一般使用锁来保证数据的一致性。MySQL中也提供了乐观锁和悲观锁两种机制,本文将详细讲解这两种锁的实现方式和使用场景。

悲观锁

悲观锁是一种在访问数据时悲观地认为其他线程可能会修改数据,因此对数据进行加锁处理,从而保证数据的一致性。通常情况下,悲观锁会在执行SQL语句时自动加锁,如下所示:

SELECT * FROM student WHERE id = 1 FOR UPDATE;

上面的SQL语句中使用了FOR UPDATE关键字,表示当前查询会涉及到数据修改,因此需要对查询结果加锁。

悲观锁的优缺点

悲观锁的优点是实现简单,易于理解和掌握。但是悲观锁会对性能造成一定的影响,因为悲观锁可能会导致多个线程之间互相等待,从而影响程序的并发性能。

悲观锁的示例

下面的示例演示了在MySQL中使用悲观锁实现多线程同时修改同一条数据的操作。

import threading
import time
import pymysql

def update_score(conn):
    cur = conn.cursor()
    # 使用悲观锁更新数据
    cur.execute("SELECT * FROM score WHERE id = 1 FOR UPDATE")
    score = cur.fetchone()[1]
    score += 10
    cur.execute("UPDATE score SET score = %s WHERE id = 1", (score,))
    conn.commit()
    cur.close()

conn = pymysql.connect(host='localhost', user='root', password='password', database='test', port=3306)
threads = []
for i in range(10):
    t = threading.Thread(target=update_score, args=(conn,))
    threads.append(t)

for t in threads:
    t.start()

for t in threads:
    t.join()

conn.close()

乐观锁

乐观锁是一种在访问数据时乐观地认为其他线程不会修改数据,因此不加锁直接执行操作。在操作完成前,如果发现数据已经被其他线程修改,则需要进行回滚操作。常用的乐观锁实现方式是通过增加一个版本号字段来实现,下面是一个示例:

CREATE TABLE goods (
  id INT(11) NOT NULL,
  name VARCHAR(255),
  price INT(11) NOT NULL DEFAULT '0',
  version INT(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

在这个示例中,goods表中增加了一个version字段,用于记录当前数据的版本号。在执行更新操作时,会先查询当前数据的版本号,然后将新的版本号更新到表中,如果查询到的版本号和更新前的版本号不一致,则说明数据已经被其他线程修改,需要回滚操作。

乐观锁的优缺点

乐观锁的优点是能够提高程序的并发性能,因为大多数情况下,数据访问不会涉及到冲突。但是乐观锁需要特殊的机制来处理并发访问,因此实现相对复杂。

乐观锁的示例

下面的示例演示了在MySQL中使用乐观锁实现多线程同时修改同一条数据的操作。

import threading
import time
import pymysql

def update_goods(conn):
    cur = conn.cursor()
    while True:
        try:
            # 开启事务
            conn.begin()
            # 查询当前的版本号
            cur.execute("SELECT version FROM goods WHERE id = 1")
            version = cur.fetchone()[0]
            # 将版本号加1并更新数据
            cur.execute("UPDATE goods SET price = price + 10, version = version + 1 WHERE id = 1 AND version = %s", (version,))
            # 提交事务
            conn.commit()
            break
        except pymysql.err.InternalError:
            conn.rollback()
            time.sleep(0.1)

conn = pymysql.connect(host='localhost', user='root', password='password', database='test', port=3306)
threads = []
for i in range(10):
    t = threading.Thread(target=update_goods, args=(conn,))
    threads.append(t)

for t in threads:
    t.start()

for t in threads:
    t.join()

conn.close()

总结

在多线程编程中,锁是保证数据一致性的重要机制之一。本文详细介绍了MySQL中的乐观锁和悲观锁,包括悲观锁的实现方式、优缺点以及示例,以及乐观锁的实现方式、优缺点以及示例。在实际开发中,需要根据具体的业务需求来选择适合的锁机制。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:实例讲解MySQL中乐观锁和悲观锁 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • SQL Server 的高可用性和灾难恢复的区别

    SQL Server 的高可用性和灾难恢复都是保障数据可靠性的方式,但它们的实现和应用场景是不同的。 高可用性 高可用性通常是指在系统运行过程中,持续保持系统服务的可用性,避免因单点故障而造成业务中断。 SQL Server 的高可用性实现方式有以下几种: Always On 可用性组 Always On 可用性组是 SQL Server 2012 引入的一…

    database 2023年3月27日
    00
  • MySQL数据库事务与锁深入分析

    MySQL数据库事务与锁深入分析 什么是事务 事务是指为了保证数据的一致性,在数据库中执行的一组操作单元,要么全部执行,要么全部不执行。事务通常包括以下四个特性(RDBMS中称作ACID): 原子性(Atomicity):一个事务内的所有操作,要么全部提交成功,要么全部失败回滚。 一致性(Consistency):事务执行前后,数据总量及数据约束关系保持一致…

    database 2023年5月21日
    00
  • navicat创建MySql定时任务的方法详解

    Navicat创建MySQL定时任务的方法详解 MySQL定时任务是一种非常常用的数据库操作方式,它可以在指定的时间周期内执行指定的SQL脚本。 Navicat是一款常用的数据库管理工具,可以方便地对MySQL数据库进行管理,也可以很方便地创建MySQL定时任务。 下面详细介绍一下Navicat创建MySQL定时任务的方法: 步骤一:连接MySQL数据库 首…

    database 2023年5月22日
    00
  • 详解SQL四种语言:DDL DML DCL TCL

    详解SQL四种语言:DDL、DML、DCL、TCL SQL(Structured Query Language)是关系型数据库管理系统的标准语言。SQL语言包括DDL、DML、DCL、TCL四种语言。下面将详细介绍这四种语言的含义、语法和示例。 DDL DDL(Data Definition Language,数据定义语言)是用于定义数据库对象的语言,主要包…

    database 2023年5月22日
    00
  • SQL数据查询之DQL语言介绍

    我会为您详细讲解“SQL数据查询之DQL语言介绍”的完整攻略。 DQL语言介绍 什么是DQL语言 DQL(Data Query Language)是数据库查询语言,主要用于从数据库中查询、检索和过滤数据。DQL语言包含了很多常用的关键字例如SELECT、FROM、WHERE、GROUP BY、HAVING等,可以通过这些关键字组合出各种复杂的数据查询语句。 …

    database 2023年5月21日
    00
  • oracle停止数据库后linux完全卸载oracle的详细步骤

    针对这个问题,我为您提供以下详细步骤: 停止oracle数据库 在Linux系统中,使用以下命令停止oracle数据库: sqlplus / as sysdba shutdown immediate; exit; 回到Linux系统命令行界面 使用以下命令回到Linux系统的命令行界面: exit; 卸载oracle软件 使用以下命令卸载oracle软件: …

    database 2023年5月22日
    00
  • MySQL——修改root密码的4种方法(以windows为例)

    方法1: 用SET PASSWORD命令 首先登录MySQL。 格式:mysql> set password for 用户名@localhost = password(‘新密码’); 例子:mysql> set password for root@localhost = password(‘123’); 方法2:用mysqladmin 格式:my…

    MySQL 2023年4月16日
    00
  • 教你如何在MySQL命令行中使用SQL语句的规则

    下面是“教你如何在MySQL命令行中使用SQL语句的规则”的完整攻略。 1. 进入MySQL命令行 首先,打开终端或命令行界面,输入以下命令: mysql -u 用户名 -p 其中,用户名是你在MySQL数据库中的用户名。输入完后,按下回车键,接着会提示你输入密码。输入正确的密码即可进入MySQL命令行。 2. 创建、选择和删除数据库 创建数据库 要创建一个…

    database 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部