首页 数据库 mysql教程 MySQL中的事务与锁

MySQL中的事务与锁

Feb 06, 2017 am 11:12 AM

这篇文章详细介绍一下数据库事务与锁的相关知识。主要是一些概念性的东西看起来可能比较乏味,但作为一名合格的程序员来说,你应该掌握也必须掌握。这些理论知识好比是一个人的内功,我们平时敲代码是外功,只有内外兼修,相互促进,才能达到武林高手的境界。好了废话不多说,下面开始。

数据库事务

事务的边界

事务的开始边界(begin) 
事务的结束边界(commit):提交事务,永久保存被事务更新后的数据库状态。 
事务的异常结束边界(rollback):撤销事务,使数据库退回到执行事务前的初始状态。

每启动一个MySQL.exe程序,就会得到一个单独的数据库连接。每个数据库连接都有一个全局变量autocommit,表示当前的事务模式,它有两个值可选:

  • 0:表示手工提交模式

  • 1:表示自动提交模式,默认值

我们可以查看和修改这个值。

数据库事务的4个特性(ACID):

  • 原子性(Atomicity):事务是一个原子操作单元,其对数据的修改,要么全部执行,要么全都不执行;

  • 一致性(Consistent):在事务开始和完成时,数据都必须保持一致状态;

  • 隔离性(Isolation):数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行;

  • 持久性(Durable):事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。

事务隔离级别

数据库事务隔离级别,只是针对一个事务能不能读取其它事务的中间结果。

878.jpg

  • Read Uncommitted (读取未提交内容) 
    在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读( Dirty Read )。

  • Read Committed (读取提交内容) 
    这是大多数数据库系统的默认隔离级别(但不是 MySQL 默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读( Nonrepeatable Read ),因为同一事务的其他实例在该实例处理其间可能会有新的 commit ,所以同一 select 可能返回不同结果。

  • Repeatable Read (可重读) 
    这是 MySQL 的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 ( Phantom Read )。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的 ” 幻影 ” 行。 InnoDB和 Falcon 存储引擎通过多版本并发控制( MVCC , Multiversion Concurrency Control )机制解决了该问题。

  • Serializable (可串行化) 
    这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。

隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。 
对于多数应用程序,可以有效考虑把数据库系统的隔离级别设为Read Committed,它能够避免脏读,而且具有较好的并发性能。尽管它会导致不可重复读、虚度和第二类丢失更新这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁和乐观锁来控制。

事务的传播性

  1. PROPAGATION_REQUIRED 
    加入当前正要执行的事务,如果当前事务不存在,那么就起一个新的事务。Spring 操作数据库默认的事务传播行为就是 propagation_required 。

  2. PROPAGATION_SUPPORTS 
    如果当前在事务中,即以事务的形式运行,如果当前不再一个事务中,那么就以非事务的形式运行.

  3. PROPAGATION_MANDATORY 
    必须在一个事务中运行。也就是说,他只能被一个父事务调用。否则,他就要抛出异常。

  4. PROPAGATION_REQUIRES_NEW 
    挂起当前事务,另起一个新的事务。

  5. PROPAGATION_NOT_SUPPORTED 

    当前不支持事务。如果在事务中,会挂起当前事务,自己以非事务的行为运行。

  6. PROPAGATION_NEVER 
    不能在事务中运行,如果在事务中运行就会抛出异常。

  7. PROPAGATION_NESTED 
    嵌套的事务依赖父事务,父事务提交,它跟着提交,父事务回滚,它跟着回滚。

行级锁

Mysql中三种类型的锁:

行级:引擎 INNODB , 单独的一行记录加锁 
页级:引擎 BDB,一次锁定相邻的一组记录。 
表级:引擎 MyISAM , 理解为锁住整个表,可以同时读,写不行。 
三种锁的特性可大致归纳如下: 
1) 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。 
2) 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。 
3) 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

我们这里主要谈论的是行级锁,一般的在秒杀系统中我们会对商品库存使用行级锁,因为秒杀的时候库存是一个很重要的数据,我们在创建数据库的表时可能会出现下面这样的设置:

ENGINE = InnoDB AUTO_INCREMENT=10 DEFAULT CHARACTER SET = utf8 comment='用户表
登录后复制

将引擎设置为InnoDB,InnnoDB与其他引擎的不同:一是支持事务(TRANCSACTION),二是采用了行级锁。

InnoDB中两种模式的行级锁:

1)共享锁:允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
( Select * from table_name where ……lock in share mode)
2)排他锁:允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和 排他写锁。(select * from table_name where…..for update)

为了允许行锁和表锁共存,实现多粒度锁机制;同时还有两种内部使用的意向锁(都是表锁),分别为意向共享锁和意向排他锁。

  • 意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。

  • 意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。

注意:InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但是如果是使用相同的索引键,是会出现锁冲突的。应用设计的时候要注意这一点。

行级锁的优缺点

行级锁定的优点:

  • 当在许多线程中访问不同的行时只存在少量锁定冲突。

  • 回滚时只有少量的更改。

  • 可以长时间锁定单一的行。

行级锁定的缺点:

  • 比页级或表级锁定占用更多的内存。

  • 当在表的大部分数据上使用时,比页级或表级锁定速度慢,因为你必须获取更多的锁。如果你在大部分数据上经常进行GROUP BY操作或

者必须经常扫描整个表,比其它锁定明显慢很多。

hibernate中通过行级锁实现的悲观锁。

一些例子:

假设有个表单products ,里面有id跟name二个栏位,id是主键。
1: 明确指定主键,并且有此条记录,执行row lock。若查无此记录,无lock。

SELECT * FROM products WHERE id='3' FOR UPDATE;SELECT * FROM products WHERE id='3' and name="cat" FOR UPDATE;
登录后复制

2: 无主键,执行table lock。

SELECT * FROM products WHERE name='Mouse' FOR UPDATE;
登录后复制

3: 主键不明确,table lock。

SELECT * FROM products WHERE id<>&#39;3&#39; FOR UPDATE;
登录后复制

注意: FOR UPDATE仅适用于InnoDB,且必须在事务块(BEGIN/COMMIT)中才能生效。此外,如果A与B都对表id进行查询但查询不到记录,则A与B在查询上不会进行row锁,但A与B都会获取排它锁,此时A再插入一条记录的话则会因为B已经有锁而处于等待中,此时B再插入一条同样的数据则会抛出Deadlock found when trying to get lock; try restarting transaction。然后释放锁,此时A就获得了锁而插入成功。

以上就是MySQL中的事务与锁的内容,更多相关内容请关注PHP中文网(www.php.cn)!


本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

如何使用Alter Table语句在MySQL中更改表? 如何使用Alter Table语句在MySQL中更改表? Mar 19, 2025 pm 03:51 PM

本文讨论了使用MySQL的Alter Table语句修改表,包括添加/删除列,重命名表/列以及更改列数据类型。

如何为MySQL连接配置SSL/TLS加密? 如何为MySQL连接配置SSL/TLS加密? Mar 18, 2025 pm 12:01 PM

文章讨论了为MySQL配置SSL/TLS加密,包括证书生成和验证。主要问题是使用自签名证书的安全含义。[角色计数:159]

说明InnoDB全文搜索功能。 说明InnoDB全文搜索功能。 Apr 02, 2025 pm 06:09 PM

InnoDB的全文搜索功能非常强大,能够显着提高数据库查询效率和处理大量文本数据的能力。 1)InnoDB通过倒排索引实现全文搜索,支持基本和高级搜索查询。 2)使用MATCH和AGAINST关键字进行搜索,支持布尔模式和短语搜索。 3)优化方法包括使用分词技术、定期重建索引和调整缓存大小,以提升性能和准确性。

哪些流行的MySQL GUI工具(例如MySQL Workbench,PhpMyAdmin)是什么? 哪些流行的MySQL GUI工具(例如MySQL Workbench,PhpMyAdmin)是什么? Mar 21, 2025 pm 06:28 PM

文章讨论了流行的MySQL GUI工具,例如MySQL Workbench和PhpMyAdmin,比较了它们对初学者和高级用户的功能和适合性。[159个字符]

您如何处理MySQL中的大型数据集? 您如何处理MySQL中的大型数据集? Mar 21, 2025 pm 12:15 PM

文章讨论了处理MySQL中大型数据集的策略,包括分区,碎片,索引和查询优化。

如何使用Drop Table语句将表放入MySQL中? 如何使用Drop Table语句将表放入MySQL中? Mar 19, 2025 pm 03:52 PM

本文讨论了使用Drop Table语句在MySQL中放下表,并强调了预防措施和风险。它强调,没有备份,该动作是不可逆转的,详细介绍了恢复方法和潜在的生产环境危害。

您如何用外国钥匙代表关系? 您如何用外国钥匙代表关系? Mar 19, 2025 pm 03:48 PM

文章讨论了使用外国密钥来代表数据库中的关系,重点是最佳实践,数据完整性和避免的常见陷阱。

如何在JSON列上创建索引? 如何在JSON列上创建索引? Mar 21, 2025 pm 12:13 PM

本文讨论了在PostgreSQL,MySQL和MongoDB等各个数据库中的JSON列上创建索引,以增强查询性能。它解释了索引特定的JSON路径的语法和好处,并列出了支持的数据库系统。

See all articles