一、事务的隔离级别/锁问题

基本的介绍: 当我们的mysql表,被多个线程或者客户端同时操作时,mysql提供一种机制,可以让不同的事务在操作数据时,具有隔离性。

锁是计算机协调多个进程或线程并发访问某一资源的机制。锁冲突也是影响数据库并发访问性能的一个重要因素。MySQL不同的存储引擎支持不同的锁机制,如 MyISAM MEMORY 存储引擎采用表级锁BDB 采用页面锁,也支持表级锁;InnoDB 既支持行级锁也支持表级锁,默认采用行级锁

表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低;

行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高;

页面锁:开销和加锁时间介于表锁和行锁之间;会出现死锁;锁定粒度介于表锁和行锁之间,并发度一般;

锁冲突:例如说事务A将某几行上锁后,事务B又对其上锁,锁不能共存否则会出现锁冲突。(但是共享锁可以共存,共享锁和排它锁不能共存,排它锁和排他锁也不可以)

死锁:例如说两个事务,事务A锁住了1~5行,同时事务B锁住了6~10行,此时事务A请求锁住6~10行,就会阻塞直到事务B施放6~10行的锁,而随后事务B又请求锁住1~5行,事务B也阻塞直到事务A释放1~5行的锁。死锁发生时,会产生Deadlock错误。两个事务都需要获得对方持有的排他锁才能继续完成事务,形成循环锁成死锁。如果锁是对表操作的,所以自然锁住全表的表锁就不会出现死锁。

Show Innodb status 命令查看最后一个死锁的产生原因。

从锁的角度看,表级锁更适合用于以查询为主,只有少量按索引条件更新数据的应用;而行级锁更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用。

二、MyISAM 表锁

查询表级锁征用情况:

Show status like ‘table%’;

如果 table_locks_waited 值较高,则说明存在较严重的表级锁征用情况;

对于MyISAM表

读锁表共享读锁,不会阻塞其他用户对同一表的请求,但会阻塞请求(即我读的时候我不能改,你能读也不能写【写等待】);

直到解锁表才执行:

写锁表独占写锁,则即阻塞也阻塞(我能读写,你不能读且不能写【读写等待】);

读写互斥(别人在读的时候你不能写,在写的时候不能读),但在一定条件下,也支持查询和插入操作的并发进行,设置系统变量concurrent_insert 值为0,1,2

MyISAM 在执行 SELECT 前,自动 给涉及的所有表加 读锁,执行 UPDATE、DELETE|、INSERT 等前,自动写锁;一般不需要手动显示加锁。

MyISAM 总是一次获得SQL语句所需的全部锁,所以不会出现死锁;

在执行 LOCK TABLES 后,只能访问显示加锁的这些表,不能访问未加锁的表,自动加锁的情况也是如此;

如果SQL中出现锁定表取表名的,也需要显示申明锁定别名表

Lock  tables  a  read,  b  read ; # 同时锁定 a, b表

给MyISAM表显式加锁,一般是为了在一定程度模拟事务操作,实现对某一时间点多个表的一致性读取。例如有一个订单表,其中记录有各订单的总金额total,同时还有一个订单明细表 order_detail, 其中记录有各个订单每一产品的金额小计 subtotal, 假设我么要检查这两个表的金额合计是否相符,就需要给两个表加 读锁 ,防止在第一个表统计的过程中, order_detail 表已经发生了改变。

MyISAM的锁调度:

MyISAM的读锁和写锁互斥,读写操作是串行的。那么,一个进程请求读锁,同时另一个进程请求同一表的写锁,写进程优先获得锁,即使读请求先到锁等待队列,写请求后到,写锁也会插队到读锁请求之前。这也是MyISAM不适合有大量更新操作和查询操作应用的原因。因为有大量的更新操作会造成查询操作很难获得读锁,从而可能永久阻塞。尽量避免长时间运行的查询操作,如复杂查询不可避免,尽量安排在数据库空闲时段执行,如夜间

解决查询相对重要的应用中读锁等待严重的问题

1.指定启动参数low_priority_updates,使MyISAM引擎给予读请求以优先的权利

2.命令set low_priority_updates = 1,使该连接发出的更新请求优先级降低

3.指定insert、update、delete语句的low_priority属性,降低该语句的优先级

4.折中,系统参数max_write_lock_count设置一个合适的值,当一个表的读锁达到这个值后,MySQL就暂时将写请求的优先级降低,给读进程一定获得锁的机会;

并发插入(系统变量concurrent_insert

concurrent_insert = 0 ,不允许并发插入

concurrent_insert = 1,如果MyISAM表中没有空洞(没有被删除的行),MyISAM允许在一个进程读表的同时,另一个进程从表尾插入记录。Mysql的默认设。比如,线程session1执行 lock table test read local 语句后就不能对该表写操作(innodb的不行,还是写等待)。但另一个线程session2虽然不能更新和删除,但却可以在尾部并发插入操作,且插入的数据在session1没有释放锁时是无法查询到的。

concurrent_insert =2,无论有没有空洞,都允许在表尾并发插入记录

  利用MyISAM的并发插入来解决应用中对同一表查询和插入的锁争用。通过定期在系统空闲时执行 optimize table 语句来整理空间碎片,回收因删除而产生的中间空洞。

三、查看Innodb行锁争用情况

Show status like ‘innodb_row_lock%’;

Innodb_row_waits 和 Innodb_row_lock_time_avg 的值比较高,可

查看 information_schema 数据库中相关的表,如 innodb_locks 和 innodb_lock_waits;

通过设置 Innodb monitors 来观察锁冲突情况:

Create table innodb_monitor(a int) engine=innodb;

然后 Show engine innodb status\G 查看

Drop table innodb_monitor; //停止监视器,默认情况下每15秒写入监控日志

四、Innodb实现两种类型的行锁(针对开启事务,否则无效)

  innodb 表锁操作跟 myisam 一样。与MyISAM最大的不同点有两点,一是支持事务,二是采用了行级锁。

  共享锁(S:读锁。当一个事务(必要条件否则无效)对某几行上读锁时,我可以读写允许其他事务对这几行进行读操作,但不允许其进行写操作,也不允许其他事务给这几行上排它锁,但允许上读锁

上共享锁的写法select 语句 … lock in share mode

  

  

  

  

  得出结论:允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。注意:如果两个事务都对同一条数据上了共享锁,然后session1 要更新这条数据(会写等待),若此时session2 也对这条数据进行更新(则会造成死锁导致退出),session1的写执行。

排他锁(X:写锁。当一个事务对某几个上写锁时,不允许其他事务写,但允许读。更不允许其他事务给这几行上任何锁。包括写锁。

上排它锁的写法select 语句 … for update

  

  

  如果一个事务请求的锁模式与当前线程的锁兼容,Innodb 就将请求的锁授予该事务;反之,如果两者不兼容,该事务就要等待锁释放。

  即同时获得共享锁,但不能同时获得排他锁,会锁等待

  

  对于 UPDATEDELETEINSERT 语句,InnoDB会自动给涉及数据集加排他锁X;对于普通的 SELECT 语句,InnoDB不会加任何锁。意向锁是系统自动加的。

  

  

  

  

  得出结论:排他锁,允许获的排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁排他写锁

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

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

注意几点:

  1. Innodb行锁是通过给索引上的索引项加锁来实现。如果没有索引将通过隐藏的聚簇索引来对记录加锁,即如果不通过索引条件检索数据,将对表中所有记录加锁,实际效果跟表锁一样
  2. 两个事务不能锁同一个索引
  3. insert ,delete , update在事务中都会自动默认加上排它锁
  4. 在没有索引的情况下,Innodb会对所有记录都加锁,当给其增加一个索引后,Innodb只锁定了符合条件的行。
  5. 访问不同行的记录,但如果使用相同索引键,会出现锁冲突

  

  

  

  

  

MySQL事务(二)的更多相关文章

  1. MySQL系列(二)---MySQL事务

    MySql 事务 目录 MySQL系列(一):基础知识大总结 MySQL系列(二):MySQL事务 什么是事务(transaction) 保证成批操作要么完全执行,要么完全不执行,维护数据的完整性.也 ...

  2. MySQL事务提交过程(二)

    上一篇文章我们介绍了在关闭binlog的情况下,事务提交的大概流程.之所以关闭binlog,是因为开启binlog后事务提交流程会变成两阶段提交,这里的两阶段提交并不涉及分布式事务,当然mysql把它 ...

  3. MySQL事务隔离级别(二)

    搞清楚MySQL事务隔离级别 首先创建一个表 account.创建表的过程略过(由于 InnoDB 存储引擎支持事务,所以将表的存储引擎设置为 InnoDB).表的结构如下: 为了说明问题,我们打开两 ...

  4. Mysql事务探索及其在Django中的实践(二)

    继上一篇<Mysql事务探索及其在Django中的实践(一)>交代完问题的背景和Mysql事务基础后,这一篇主要想介绍一下事务在Django中的使用以及实际应用给我们带来的效率提升. 首先 ...

  5. MySQL入门详解(二)---mysql事务、锁、以及优化

    MySQL 事务主要用于处理操作量大,复杂度高的数据.比如说,在一个商城系统中,用户执行购买操作,那么用户订单中应该加一条,库存要减一条,如果这两步由于意外只进行了其中一步那么就会发生很大的问题.而事 ...

  6. 二十三、MySQL 事务

    MySQL 事务 MySQL 事务主要用于处理操作量大,复杂度高的数据.比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数 ...

  7. MySQL事务(二)事务隔离的实现原理:一致性读

    今天我们来学习一下MySQL的事务隔离是如何实现的.如果你对事务以及事务隔离级别还不太了解的话,这里左转. 好的,下面正式进入主题.事务隔离级别有4种:读未提交.读提交.可重复读和串行化.首先我们来说 ...

  8. MYSQL事务和锁

    mysql事务(一)—转载 2012年12月20日 ⁄ Mysql数据库, 技术交流 ⁄ 暂无评论 一. 什么是事务 事务就是一段sql 语句的批处理,但是这个批处理是一个atom(原子) ,不可分割 ...

  9. MySQL优化二(连接优化和缓存优化)

    body { font-family: Helvetica, arial, sans-serif; font-size: 14px; line-height: 1.6; padding-top: 10 ...

  10. MySQL(十三)之MySQL事务

    前言 这段时间自己会把之前学的东西都总结一遍,希望对自己以后的工作中有帮助.其实现在每天的状态都是很累的,但是我要坚持! 进入我们今天的正题: 为什么MySQL要 有事务呢?事务到底是用来干什么的?我 ...

随机推荐

  1. Hakase and Nano 【思维博弈】

    Hakase and Nano 时间限制: 1 Sec  内存限制: 128 MB 提交: 400  解决: 104 [提交] [状态] [命题人:admin] 题目描述 Hakase and Nan ...

  2. POJ 3264 Balanced Lineup (线段树查找最大最小值)

    http://poj.org/problem?id=3264 题意:给你一个长度为n的序列a[N] (1 ≤ N ≤ 50000),询问Q(1 ≤ Q ≤ 200000) 次,每次输出[L, R]区间 ...

  3. 论操作系统的IO

    论事件驱动与异步IO - 简书 https://www.jianshu.com/p/814c7e7c4647

  4. P4609 [FJOI2016]建筑师

    思路 裸的第一类斯特林数,思路和CF960G相同 预处理组合数和第一类斯特林数回答即可 代码 #include <cstdio> #include <cstring> #inc ...

  5. Ubuntu18.04安装Android Studio

    一.安装JDK JDK下载地址:https://www.oracle.com/technetwork/java/javase/downloads/jdk11-downloads-5066655.htm ...

  6. Chrome上的扩展工具

    rest client - rest api Testing:类似fiddler的工具,可以测试url,查看返回值……

  7. Linux命令2——b

    badblocks:检查磁盘设备中损坏的区块 -b:指定磁盘的区块大小,单位:字节 -c:一次检查几个区块 -i:由文件总读取已知的损坏区块,检查时会忽略这些区块 -o:检查的结果写入指定的输出文件. ...

  8. Robot Framework+AutoItLibrary使用

    目的:用Robot Framework测试win7桌面程序   因为安装完了才补的记录,估计有错漏:(     步骤: 1. 尝试pip install AutoItLibrary 失败 2. 下载A ...

  9. 【Oracle】【问题】

    1. java.sql.SQLException: 对只转发结果集的无效操作: last 参考:https://www.cnblogs.com/gaoyuchuanIT/articles/411888 ...

  10. CentOS6.5下安装、配置SSH

    1.登录CentOS 6.5系统,使用root用户登录,如果为非root用户则执行 su 或 su - 或 su root 或 su - root 输入root密码切换为root用户. 2.查看SSH ...