mysql + spring transaction

背景是调用一个外部接口要做集群限流、想到不依赖过多中间件的方法就是用db的唯一性、比如集群限制并发限制每秒最多调用10次

遇到的问题:
1. 调用限制是基于秒为单位、create_time的定义是timestamp、mysql保存timestamp是毫秒时间还是秒级时间、用一个YY-MM-DD hh:mm:ss的时间格式是否能筛选出条件、当时问题比较多、这块儿为了保险起见又弄了个varchar的字段保存创建时间的秒级表示、后来用create_time用字符串匹配也可以匹配出来、mysql时间存储的细节后面可以多挖下, 后面就用create time就是好用的
2. mybatis的cache问题、当时多个相同的transaction运行、debug发现第一个transaction(t1)运行完了之后、后续其他相同的transaction(t2、t3)拿不到t1新写入的记录、但是debug截断时用相同的sql在mysql terminal执行可以拿到t1新写入的记录、第一个反应就是后续的transaction没有真正的执行db而是用了mybatis的cache、用了flushCache = true 和useCache = false后、debug执行进入mybatis里发现、确实执行的是查询db、拿到数值依然是过期的,关于mybatis的cache设计、面试的时候也经常和别人聊、后面可以细化一下后面、比如为啥这样设计、缘由等等
3. mysql的mvcc、这个东西我一直就知道、在实际用的时候似乎没什么概念、我是用spring的@Transactional实现的事务、t2debug截断时其实已经进入了事务、此时它获取得到是t1未能生效的镜像读(snapshot read、mysql默认是RR)、而在mysql terminal里读的时候t1已经执行完了、获取当前最新的snapshot read就是t1执行的结果。因为spring@Transactional的实现是基于spring aop后面实现的Bean post processor、这里因为没有实现接口所以走的cglib的实现、它构造了一个子类继承目标类、在方法执行之前处理Transaction相关的东西(比如开启事物、设置autocommit等等)、当时换了一个思路上来就插入记录、假如成功了就是这一秒钟的第一个记录成功放回、假如失败了用悲观锁hold住这条记录做上界判断、计数+1、伪代码如下、为了防止各个服务器的时间误差、统一用db的时间来衡量


image.png

最开始用唯一索引做悲观锁的条件、但是同时并发请求数目大于20后基本上一定会出死锁、当时想当然的认为是gap的问题、unquie index一把锁、带上cluster index一把锁、几十个Transaction同时运行、假如顺序不对会发生死锁的、但是为了尝试干脆用create time做primary key、查询悲观锁的条件也用primary key、每次只有一把record lock应该就不会出问题了、这样改造完运行、2-3个并发请求必出死锁、盲目的改隔离界别和传播级别都不管用、有时候没有理论指导乱尝试是非常低效的、死锁日志如下:


image.png

当时搞到夜里3点多、怎么想也不明白为啥会有S锁的问题、没有刻意加S锁、后来请教dba同学、后来发现这一段笔记一直安静的睡在我的OneNote里

image.png

innodb engine在唯一索引或者primary的情况下、并发插入时失败的Transaction会在对应记录上加上S锁、失败的Transaction上后续使用悲观锁、基本上一定会出deadlock、所以插入失败后应该结束当前的Transaction、用一个新的Transaction去争抢失败的记录、发生DuplicateKeyException时(继承自RuntimeException)spring-tx里在方法异常时会rollback事务、放弃那把S锁、伪代码如下:

while(true){
        try{
            tryToInsert
            break;
        }catch(DuplicateKeyException){
            if waitUpdate suc
                break;
        }
    }
  1. 上面tryToInsert和waitUpdate 都加了@Transactional, waitUpdate 方法也指定了开启一个新事物REQUEST_NEW, 但是发现waitUpdate 中后续每一个事务是并发执行的、比如t1插入成功、t2和t3同时都拿到了这条记录(count = 1)、然后并发更新出错、最后count = 2而不是3、后来加入了Transaction support打印当前事务状态、发现waitUpdate 虽然加了@Transactional注解但是根本不在事务里、想了一下BPP执行后代理对象代替原来的bean、经过代理对象的方法引用才能执行前置和后置处理、public方法间的对象调用不经过代理对象(因为代理类继承目标类、目标类执行方法中找到的是目标的方法而不是代理类继承的方法)、包了一层引用、测试166的并发限制17秒全部出去、waitUpdate 设置了一个比较大的timeout、这样并发量比较大的时候后续的Transaction因为悲观锁的等待出现了些show sql的警示、比如瞬间几千个qps打过来、这样报警而排查没有啥意义、后续改成乐观锁、既增加了并发度还去掉了无意义的slow sql

总结一下:
1. 每一个知识点都知道、也自认为了解、但是在实际的过程中却并不那么顺畅、天下之事,闻者不如见者知之为详,见者不如居者知之为尽
2. 再有能灵活运用的东西才是自己、而不是安静沉睡的笔记
3. 其实最简单的办法是每个机器加一个保守的sleep、比如2台机器sleep 200ms、这样不会出错、但是两个请求打到一个机器会效率慢、增加机器要调整sleep的时间、做调用频率的统计不那么方便;但是手上其实还要其他工作要做、客观上头天弄到3点多、第二天上班会影响工作效率、所以第二天强迫自己抽出来(这与人本身的求知欲和解决问题的欲望是相悖的)、应该是做个临时work的版本、不忙的时候搞定它、这个问题就是周末的凌晨搞定的、客服人本身的情绪缺陷合理高效的安排工作

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容