行锁的等待
创新互联建站专注为客户提供全方位的互联网综合服务,包含不限于做网站、成都网站制作、镇赉网络推广、微信平台小程序开发、镇赉网络营销、镇赉企业策划、镇赉品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们最大的嘉奖;创新互联建站为所有大学生创业者提供镇赉建站搭建服务,24小时服务热线:13518219792,官方网址:www.cdcxhl.com
在介绍如何解决行锁等待问题前,先简单介绍下这类问题产生的原因。产生原因简述:当多个事务同时去操作(增删改)某一行数据的时候,MySQL 为了维护 ACID 特性,就会用锁的形式来防止多个事务同时操作某一行数据,避免数据不一致。只有分配到行锁的事务才有权力操作该数据行,直到该事务结束,才释放行锁,而其他没有分配到行锁的事务就会产生行锁等待。如果等待时间超过了配置值(也就是 innodb_lock_wait_timeout 参数的值,个人习惯配置成 5s,MySQL 官方默认为 50s),则会抛出行锁等待超时错误。
如上图所示,事务 A 与事务 B 同时会去 Insert 一条主键值为 1 的数据,由于事务 A 首先获取了主键值为 1 的行锁,导致事务 B 因无法获取行锁而产生等待,等到事务 A 提交后,事务 B 才获取该行锁,完成提交。这里强调的是行锁的概念,虽然事务 B 重复插入了主键,但是在获取行锁之前,事务一直是处于行锁等待的状态,只有获取行锁后,才会报主键冲突的错误。当然这种 Insert 行锁冲突的问题比较少见,只有在大量并发插入场景下才会出现,项目上真正常见的是 updatedelete 之间行锁等待,这里只是用于示例,原理都是相同的。
三、产生的原因根据我之前接触到的此类问题,大致可以分为以下几种原因
2019-06-03 补充
此等锁表必须有两个条件:
首先历史原因,线上加索引是用了一个存储过程:
摒弃一切无关要素,我们只看核心语句:
线上用的就是这么一个语句添加索引的。
首先,添加索引为什么会锁表呢?查阅一些资料说,如果当前表正在执行一个慢查询,此时添加索引,就可能会锁表。
我尝试在测试环境重现了一下。
首先,我在b_regbroker_cst_proj这个表执行了一个慢查询事务。
这个查询正常完成要9s左右,够慢了,满足要求。
然后我要做的事情,就是在查询未完成的时间,给b_regbroker_cst_proj这个表添加索引。
好了,来试试,我先开启事务,先不提交。
然后创建索引:
哦耶,so funny。
此时无论这个表执行什么查询,都会卡住了:
查了一下下面这个lock的原因:
有没有更好的加索引解决方式呢?查文档
文档
mysql自5.6之后变提供了解决方式,运行线上无锁添加索引。
重点说两个参数:
好了,试下有没有用。
哈哈哈,卵用都没有。
我觉得我是理解错了,人家的无锁加索引,只是说加索引的语句不加锁,避免此时有update、insert、delete语句也持锁从而相互形成死锁。但是目前的问题是,有事务持了表锁,创建索引需要等待。等该事务提交,索引就能创建成功。但是在这个等待时间,其它sql都执行不了,这个很坑啊~~
结论:
总之,alter table的语句是很危险的(其实他的危险其实是未提交事物或者长事务导致的),在操作之前最好确认对要操作的表没有任何进行中的操作、没有未提交事务、也没有显式事务中的报错语句。如果有alter table的维护任务,在无人监管的时候运行,最好通过lock_wait_timeout设置好超时时间,避免长时间的metedata锁等待。
加索引要避免锁表,需要先确定此时没有慢查询事务未提交,如果这个查询卡了30分钟,那么整个表的所有业务都会卡30分钟,这是很变态的。
所以大表加索引还是在没人用的时间加比较安全,要不就是先创建副本,再将表名改掉。
处理方式:
1. 在表上建立一个聚集索引。
2. 对语句更新的相关字段建立包含索引。
如何预防死锁
1.尽量避免并发的执行涉及到修改数据的语句。
2.编写应用程序,让进程持有锁的时间尽可能短,这样其它进程就不必花太长的时间等待锁被释放。
这个是属于系统遗留问题,也就是一种系统的保护机制。就是为了避免出现这种在线修改系统的操作。
增加字段属于系统的修改操作。尽量不要在线操作,因为可能出现。未知的漏洞。一定要。离线。修改完毕,然后经过测试后。认为已经没有问题了。在。次日的凌晨发一个通知。停机维护。这样才能保证系统的正常运转。
如果在前期设置系统的时候就预留了。热升级的空间。这样才能达到在线操作的目的,而且系统的金融群总是一部分先升级。
很多情况下,你需要使用系统里边的工具集。在线修改表格。原理其实非常的简单,新建的和原表的表格结构。要一模一样。对这个表格进行修改,然后把结构变更的日期。插入进去。而且还建议您尽量在业务的低缝隙进行修改。避免发生不可控的未知状况。
使用说明:
1、如果是用 MySQL + Apache,使用的又是 FreeBSD 网络操作系统的话,安装时候你应按注意到FreeBSD的版本问题,在FreeBSD 的 3.0 以下版本来说,MySQL Source 内含的 MIT-pthread 运行是正常的,但在这版本以上,你必须使用 native threads。
2、如果在 COMPILE 过程中出了问题,请先检查你的 gcc版本是否在 2.81 版本以上,gmake 版本是否在3.75以上。
3、如果不是版本的问题,那可能是你的内存不足,请使用configure--with-low-memory 来加入。
4、如果要重新做你的configure,那么你可以键入rm config.cache和make clean来清除记录。
5、把 MySQL 安装在 /usr/local 目录下,这是缺省值,您也可以按照你的需要设定你所安装的目录。