mysql的事务,隔离级别和锁用法实例分析

 更新时间:2020年02月19日 12:11:25   作者:怀素真  
这篇文章主要介绍了mysql的事务,隔离级别和锁用法,结合实例形式分析了MySQL事务,隔离级别和锁相关原理、用法及操作注意事项,需要的朋友可以参考下

本文实例讲述了mysql的事务,隔离级别和锁用法。分享给大家供大家参考,具体如下:

事务就是一组一起成功或一起失败的sql语句。事务还应该具备,原子性,一致性,隔离性和持久性。

一、事务的基本要素 (ACID)

1、原子性:事务开始后,所有的操作,要么全部成功,要么全部失败,不可能处于中间状态,事务是一个不可分割的整体,就像原子一样。

2、一致性:事务开始前和结束后,数据库的完整性约束没有破坏,A向B转账,A扣了钱,但B却没到账。

3、隔离性:同时发生的事务(并发事务)不应该导致数据库处于不一致的状态中,每个事务都独立执行,不影响其他事务的存在。

4、持久性:事务对数据库的更改都会保存在磁盘上,不会丢失。

二、事务的并发问题

1、脏读:事务A读取了事务B未提交的写入数据,读取到的数据就称为脏数据

2、不可重复读:事务A多次读取同一数据,但在读取过程中,事务B对数据做了修改,并提交了。导致多次读取同一数据,结果不一样。

3、幻读:事务A对表中所有数据行进行了修改,比如设置status = 1,但同时,事务B往该表插入了一行新数据status = 0,对于操作事务A的用户而言,表中还有一条记录没被修改,就像发生幻觉一样。

三、事务隔离性的四个级别

事务隔离级别 脏读 不可重复读 幻读
读取未提交 read uncommitted

读已提交 read committed

×

可重复读取 repeatable read

×

×

序列化 serializable

×

×

×

四、获取和设置数据库隔离级别

SHOW VARIABLES LIKE '%isolation%';
SHOW GLOBAL VARIABLES LIKE '%isolation%';

使用系统变量查询

SELECT @@GLOBAL.tx_isolation;
SELECT @@SESSION.tx_isolation;
SELECT @@tx_isolation;

对于mysql8而言,使用下面的变量进行查询

SELECT @@GLOBAL.transaction_isolation;
SELECT @@SESSION.transaction_isolation;
SELECT @@transaction_isolation;

设置隔离级别

SET GLOBAL tx_isolation = '隔离级别';
SET SESSION tx_isolation = '隔离级别';
SET @@tx_isolation = '隔离级别';

对于mysql8而言,使用下面语句进行设置

SET GLOBAL transaction_isolation = '隔离级别';
SET SESSION transaction_isolation = '隔离级别';
SET @@transaction_isolation = '隔离级别';

五、通过例子说明各隔离级别的情况

先准备一张表,和一点数据。

CREATE TABLE `account` (
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
 `name` varchar(32) DEFAULT '' COMMENT '名称',
 `money` decimal(11,2) DEFAULT '0.00' COMMENT '金钱',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `account` (`name`, `money`) VALUES ('A', '500.00');
INSERT INTO `account` (`name`, `money`) VALUES ('B', '100.00');

1、读取未提交

set transaction_isolation = 'READ-UNCOMMITTED';
set autocommit = 0;

事务B修改了表中的数据,但是未提交,事务A确读取到了修改后的数据。如果因为某些原因,事务B回滚了,事务A读取的这个数据就是脏数据。

2、读已提交

set transaction_isolation = 'READ-COMMITTED';
set autocommit = 0;

事务B修改数据但没有提交,那么事务A仍然获取的原来数据,解决了脏读的问题。

但是事务B提交,事务A执行上一次查询,结果与上一次查询不一致,这就产生不可重复读的问题。

3、可重复读取

set transaction_isolation = 'REPEATABLE-READ';
set autocommit = 0;

事务B修改了数据并提交了,事务A两次查询的结果是一致的,解决了不可重复读的问题。

这个时候,事务A去修改name为A的money数据

name为A的money变成了350,而不是400,可重复读保证了数据的一致性。

我们重新在事务A中修改所有账号的money等于200,同时在事务B中插入一条新的数据。

事务A中获取的仍然是两条数据,解决了新增数据时,事务A出现的幻读问题。

4、序列化

set transaction_isolation = 'SERIALIZABLE';
set autocommit = 0;

事务A对表进行查询,如果没有提交,则事务B的插入语句一直等待在那里,直到超时或事务A提交。

反之,事务B对表进行插入后,没有提交,则事务A对表的查询也一直等待,直到事务B提交。

此时对表的读写都会进行锁表,当然对并发性能的影响也比较大。

隔离级别越高,越能保证数据的完整性和一致性。

六、mysql的锁

锁分为两种类型:

内部锁:mysql服务器内部执行的内部锁,以管理多个会话对表内容的争用。

外部锁:mysql为客户会话提供显式地获取表锁,以阻止其他会话访问表。

内部锁又会为两种类型:

1、行级锁:行级锁是细粒度的,只有被访问的行会被锁定,这允许多个会话同时进行写访问。

2、表级锁:mysql对myisam,memory和merge表使用表级锁,一次只允许一个会话更新表,这使得这些存储引擎更适用于以读取为主的操作。

外部锁:可以使用 LOCK TABLE 和 UNLOCK TABLE 来控制锁定。

READ (共享锁) :多个会话可以从表中读取数据而不需要获取锁,此外,多个会话可以在同一表上获得锁,当 READ 锁时,没有会话可以将数据写入表中。任何写入操作都将处于等待状态,直到 READ 锁被释放。

WRITE (排他锁) :当表被 WRITE 锁定时,除持有该锁的会话外,其他会话都不能读取或写入数据,除非 WRITE 锁被释放。

锁表的语句:

LOCK TABLES table_name [READ | WRITE];

解锁表的语句:

UNLOCK TABLES;

锁定数据库中所有表:

FLUSH TABLES WITH READ LOCK;

更多关于MySQL相关内容感兴趣的读者可查看本站专题:《MySQL索引操作技巧汇总》、《MySQL常用函数大汇总》、《MySQL日志操作技巧大全》、《MySQL事务操作技巧汇总》、《MySQL存储过程技巧大全》及《MySQL数据库锁相关技巧汇总

希望本文所述对大家MySQL数据库计有所帮助。

相关文章

  • Linux环境下mysql5.7.13安装教程

    Linux环境下mysql5.7.13安装教程

    这篇文章主要为大家详细介绍了Linux环境下mysql5.7.13安装教程,感兴趣的小伙伴们可以参考一下
    2016-07-07
  • MySQL中连接查询和子查询的问题

    MySQL中连接查询和子查询的问题

    这篇文章主要介绍了MySQL中连接查询和子查询的问题,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • MySQL如何开启用户远程登录权限

    MySQL如何开启用户远程登录权限

    这篇文章主要介绍了MySQL如何开启用户远程登录权限问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • MySQL的几种分页方式,你知道几种方式

    MySQL的几种分页方式,你知道几种方式

    这篇文章主要介绍了MySQL的几种分页方式,需要的朋友可以参考下
    2023-06-06
  • MySQL定时备份方案(利用Linux crontab)

    MySQL定时备份方案(利用Linux crontab)

    这篇文章主要给大家介绍了关于MySQL定时备份方案的相关资料,文中通过示例代码以及图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-07-07
  • MySQL多个字段拼接去重的实现示例

    MySQL多个字段拼接去重的实现示例

    在MySQL中,我们经常会遇到需要将多个字段进行拼接并去重的情况,本文就来介绍一下MySQL多个字段拼接去重的实现示例,具有一定的参考价值,感兴趣的可以了解一下
    2024-01-01
  • 详解MySQL数据库之触发器

    详解MySQL数据库之触发器

    这篇文章主要介绍了MySQL数据库之触发器的相关资料,帮助大家更好的理解和使用MySQL,感兴趣的朋友可以了解下
    2020-09-09
  • 简单了解添加mysql索引的3条原则

    简单了解添加mysql索引的3条原则

    这篇文章主要介绍了简单了解添加mysql索引的3条原则,如果表中查询的列有一个索引,MySQL能快速到达一个位置去搜寻到数据文件的中间,没有必要看所有数据,需要的朋友可以参考下
    2019-06-06
  • mysql实现不用密码登录的实例方法

    mysql实现不用密码登录的实例方法

    在本篇文章里小编给大家整理的是一篇关于mysql实现不用密码登录的实例方法,有需要的朋友们可以学习参考下。
    2020-08-08
  • 深入讲解数据库中Decimal类型的使用以及实现方法

    深入讲解数据库中Decimal类型的使用以及实现方法

    MySQL DECIMAL数据类型用于在数据库中存储精确的数值,我们经常将DECIMAL数据类型用于保留准确精确度的列,例如会计系统中的货币数据,下面这篇文章主要给大家介绍了关于数据库中Decimal类型的使用以及实现方法的相关资料,需要的朋友可以参考下
    2022-02-02

最新评论