数据库隔离级别和幻读、不可重复读的区别

举报
赵KK日常技术记录 发表于 2023/07/06 10:21:12 2023/07/06
【摘要】 数据库隔离级别和幻读、不可重复读的区别 引言在数据库系统中,隔离级别是指事务在并发执行时对数据的可见性和一致性的控制程度。幻读和不可重复读则是两种常见的并发问题,它们与隔离级别密切相关。本文将介绍数据库隔离级别,以及幻读和不可重复读的定义、区别,并且给出相关代码示例。 数据库隔离级别数据库管理系统(DBMS)为了保证事务的正确性和一致性,提供了多个隔离级别供用户选择。常见的隔离级别包括:读...

数据库隔离级别和幻读、不可重复读的区别

引言

在数据库系统中,隔离级别是指事务在并发执行时对数据的可见性和一致性的控制程度。幻读和不可重复读则是两种常见的并发问题,它们与隔离级别密切相关。本文将介绍数据库隔离级别,以及幻读和不可重复读的定义、区别,并且给出相关代码示例。

数据库隔离级别

数据库管理系统(DBMS)为了保证事务的正确性和一致性,提供了多个隔离级别供用户选择。常见的隔离级别包括:

  • 读未提交(Read Uncommitted):一个事务可以读取另一个事务未提交的数据。
  • 读已提交(Read Committed):一个事务只能读取另一个事务已经提交的数据。
  • 可重复读(Repeatable Read):一个事务在执行期间多次读取的同一数据结果是一致的。
  • 串行化(Serializable):多个事务串行执行,每个事务都像没有并发执行一样。

幻读和不可重复读

幻读

幻读是指在同一事务中,前后两次相同的查询却返回了不同的结果集。通常是由于另一个事务插入(或删除)了符合前一次查询条件的数据导致的。幻读主要发生在“读已提交”隔离级别下。

举例来说,一个事务在查询某一范围的数据时,由于另一个事务插入了新的数据行,导致第二次查询时返回了更多(或更少)的数据行,产生了幻读。

不可重复读

不可重复读是指在同一事务中,前后两次相同的查询却返回了不同的数据。通常是由于另一个事务在前一个事务读取数据期间修改或删除了符合查询条件的数据导致的。不可重复读主要发生在“可重复读”隔离级别下。

举例来说,一个事务在查询某一数据行后,另一个事务修改了该数据,导致第二次查询时返回了不同的数据内容,产生了不可重复读。

代码示例

下面是使用MySQL数据库和Python编程语言的代码示例,演示了幻读和不可重复读问题:

# 导入必要的库
import threading
import time
import pymysql

# 数据库连接配置
db_config = {
    'host': 'localhost',
    'port': 3306,
    'user': 'root',
    'password': '123456',
    'database': 'test'
}

# 初始化数据库连接
conn = pymysql.connect(**db_config)
cursor = conn.cursor()

# 创建测试表格
def create_table():
    try:
        sql = """
        CREATE TABLE IF NOT EXISTS `test_table` (
            `id` INT NOT NULL AUTO_INCREMENT,
            `name` VARCHAR(50) NOT NULL,
            PRIMARY KEY (`id`)
        )
        """
        cursor.execute(sql)
        conn.commit()
    except Exception as e:
        conn.rollback()
        print("创建表格出错:", str(e))

# 插入数据
def insert_data():
    try:
        sql = "INSERT INTO `test_table` (`name`) VALUES ('test')"
        cursor.execute(sql)
        conn.commit()
    except Exception as e:
        conn.rollback()
        print("插入数据出错:", str(e))

# 查询数据
def select_data():
    try:
        sql = "SELECT * FROM `test_table`"
        cursor.execute(sql)
        results = cursor.fetchall()
        for row in results:
            print(row)
    except Exception as e:
        print("查询数据出错:", str(e))

# 删除数据
def delete_data():
    try:
        sql = "DELETE FROM `test_table`"
        cursor.execute(sql)
        conn.commit()
    except Exception as e:
        conn.rollback()
        print("删除数据出错:", str(e))

# 测试幻读
def test_phantom_read():
    try:
        # 开启事务
        conn.begin()
        
        # 第一次查询
        print("第一次查询结果:")
        select_data()
        
        # 插入数据
        insert_data()
        
        # 第二次查询
        print("第二次查询结果:")
        select_data()
        
        # 提交事务
        conn.commit()
        
    except Exception as e:
        conn.rollback()
        print("测试幻读出错:", str(e))

# 测试不可重复读
def test_non_repeatable_read():
    try:
        # 开启事务
        conn.begin()
        
        # 第一次查询
        print("第一次查询结果:")
        select_data()
        
        # 修改数据
        update_data()
        
        # 第二次查询
        print("第二次查询结果:")
        select_data()
        
        # 提交事务
        conn.commit()
        
    except Exception as e:
        conn.rollback()
        print("测试不可重复读出错:", str(e))

# 修改数据
def update_data():
    try:
        sql = "UPDATE `test_table` SET `name`='updated' WHERE `id`=1"
        cursor.execute(sql)
        conn.commit()
    except Exception as e:
        conn.rollback()
        print("修改数据出错:", str(e))

# 创建测试表格
create_table()

# 启动两个线程进行测试
thread1 = threading.Thread(target=test_phantom_read)
thread2 = threading.Thread(target=test_non_repeatable_read)

thread1.start()
thread2.start()

thread1.join()
thread2.join()

# 关闭数据库连接
cursor.close()
conn.close()

运行以上代码后,会输出两个线程的查询结果。当隔离级别为“读已提交”时,可能会产生幻读问题,当隔离级别为“可重复读”时,可能会产生不可重复读问题。

总结

数据库隔离级别是数据库系统中保证并发执行事务正确性和一致性的重要机制。幻读和不可重复读则是并发执行时常见的问题,它们与隔离级别密切相关。幻读指同一事务中前后两次查询返回了不同的结果集,而不可重复读指同一事务中前后两次查询返回了不同的数据。合理选择隔离级别,可以避免这两种问题的发生。在实际开发中,需要根据业务需求和并发场景选择合适的隔离级别,并进行必要的测试和优化。

以上是对数据库隔离级别、幻读和不可重复读的详细介绍,并给出了相关的代码示例。希望本文能够帮助读者深入理解并发问题和隔离级别,并在实际应用中进行正确的选择和处理。

参考文献:

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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