Chinaunix首页 | 论坛 | 博客
  • 博客访问: 350637
  • 博文数量: 166
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1640
  • 用 户 组: 普通用户
  • 注册时间: 2015-05-05 11:44
个人简介

文章不在长,坚持不懈记录下努力前行的脚步

文章分类

全部博文(166)

文章存档

2017年(19)

2016年(59)

2015年(88)

我的朋友

分类: Mysql/postgreSQL

2016-02-01 11:59:47

这部分内容是基于上一节关于死锁的内容而来的Section 14.2.2.8, “Deadlock Detection AND Rollback”,它解释了为了最小化死锁我们应该如何来操作数据库,以及发生错误后如何处理的问题。

在事务性数据库中,死锁是一个典型的的问题,除非他们频繁出现使得你根本无发运行事务,一般情况下没什么危险。一般情况下,你编写的应用程序应该满足当出现死锁回滚的时候,你必须得准备重新执行事务;

InnoDB使用自动行级锁定,即使你只是插入或删除一行数据,也可能会出现死锁。那是因为这些操作并不是真正的原子的,他们自动地在插入或删除行的索引上自动的添加锁;

你可以通过下面的方式来处理死锁或者降低他们发生的可能性:
1.随时执行SHOW ENGINE INNODB STATUS命令来找出最近出现死锁的原因,对调整你的应用来来避免死锁非常有用;

2.如果频繁的出现死锁应该引起你的高度关注,启用innodb_print_all_deadlocks配置选项来获取更多的系统调试信息,这样的话,关于死锁发的信息都会被记录到error log中,不仅仅是最近的一个,调试结束后禁用掉改选项;

3.如果生产环境上不允许由于死锁导致的事务失败,那么你的应用必须有一种机制来保证事务失败回滚后的重新执行,死锁并不可怕,重新执行下回滚事务就行;

4.为了防止冲突应该保证事务小而且尽量缩短执行时间;

5.为了避免冲突细化where条件分解集合的更新,一小组更新后即可提交事务,特别地,不要让一个未提交的事务长时间的处于一个交互式的会话当中;

6.如果你的应用中使用到SELECT ... FOR UPDATE OR SELECT ... LOCK IN SHARE MODE这样的锁定读,那么你可以使用像RC这样的事务隔离级别;

7.如果在一个事务中需要对多个表或者一张表的多个地方做修改,那么每一次做这些操作都按照固定的顺序执行,那么这种类似于队列形式的顺序执行就不会产生死锁。比如,将这些操作打包成一个函数或者存储过程来调用,而不是多个具有相同顺序的insert、update、delete语句;

8.表上的索引尽量添加选择性好的,这样你的查询会扫描更少的索引设置更少的锁,用explain select来检查你的索引建立的是否合适;

9.使用更少的锁定,如果你允许select查询从一个老的快照返回数据,不要在select语句上添加FOR UPDATE或者LOCK IN SHARE MODE子句.使用RC隔离级别是一个不错的主意,因为在同一个事务中,每一个一致性读都是来自于他本身最新的快照。

10.如果还不行的话,使用表锁来使得你的事务串行化,其做法是用SET autocommit=0开启一个事务(不是start transaction)并在其后像InnoDB这样的事务表上加lock tables语句来锁表,在提交你的事务后再执行unlock tables。比如你想写t1表读t2表,那么像下面这样做:
SET autocommit=0;
LOCK TABLES t1 WRITE, t2 READ, ...;
... DO something WITH TABLES t1 AND t2 here ...
COMMIT;
UNLOCK TABLES;
表锁是为了防止同时更新同一张表,避免死锁给系统带来的开销。

11.还有一个办法是创建一个只有单行的副表来串行化事务,让没一个事务在访问表前更新这个行,用这种方式所有的事务都是以串行化的方式执行,注意在这种情况下InnoDB的死锁检测机制会检测死锁,因为串行化锁是行级锁。用MySQL的表锁,会用timeout的方式来解决死锁。
阅读(719) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~