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

基本的介绍: 当我们的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. 我为什么选择Go语言(Golang)

    作为一个以开发为生的程序员,在我心目中编程语言如同战士手里的武器,好与不好主要看使用的人是否趁手.是否适合,没有绝对的高低之分. 从2013年起,学习并使用Golang已经有4年时间了,我想叙述一下我 ...

  2. ubuntu安装微软雅黑和Consolas字体

    原文:http://fooler5.iteye.com/blog/2406227 [字体下载] YaHeiConsolas.tar:http://www.mycode.net.cn/wp-conten ...

  3. EXCEL 基本函数

    案例2:修改非法日期 TODAY(),显示今天日期,数据格式是日期,如果是常规,就是数字. EXCEL 起始日期,1900/1/1是第一天 日期输入方式要正确 时间数据格式  1:00:00  = 1 ...

  4. 题解——洛谷P2294 [HNOI2005]狡猾的商人(差分约束)

    裸的差分约束 dfs判断负环,如果有负环就false,否则就是true 注意有多组数据,数组要清空 #include <cstdio> #include <algorithm> ...

  5. (转载)c# winform 窗体起始位置 设置

    窗体起始位置为顶部中间,WinForm居中显示: ; ; this.StartPosition = FormStartPosition.Manual; //窗体的位置由Location属性决定 thi ...

  6. 【ASP.NET】System.Web.Routing - RouteCollection Class

    Provides a collection of routes for ASP.NET routing. The RouteCollection class provides methods that ...

  7. hihoCoder 1339 Dice Possibility(DP)

    http://hihocoder.com/problemset/problem/1339 题意: 求一个骰子扔n次后最后点数相加为m的概率. 思路: f[i][j]表示扔到第i次时总值为j的概率. # ...

  8. hostname命令

    hostname命令用于显示和设置系统的主机名称.环境变量HOSTNAME也保存了当前的主机名.在使用hostname命令设置主机名后,系统并不会永久保存新的主机名,重新启动机器之后还是原来的主机名. ...

  9. Java里的String类为什么是final的

    今天在看<图解设计模式>,里面出了一个问题“String类用final修饰,导致它无法被继承(扩展),这样做违反了开闭原则,这么做有什么正当理由?” 答案是效率和安全性  首先是效率,由于 ...

  10. Oracel 中的分页

    --效率低 select * from (select rownum rn, d.* from table d )p where p.rn<=20 and p.rn>=10; select ...