开心一刻 有个问题一直困扰着我:许仙选择了救蛇,为什么杨过却选择救雕(而不救蛇) 后面想想,其实杨过救神雕是有原因的,当年神雕和巨蛇打架的时候 雕对杨过说:杀蛇,杀蛇,杀蛇! ...,往 tbl_follow 插入一条记录 看似没问题,可如果我们从并发的角度来看,是不是还正常了? ... 中插了两条记录 该如何处理该问题,欢迎大家评论区留言 JVM 锁 既然并发了,那就加锁呗 JVM 自带的 synchronized 和 Lock 都有同步作用,我们以 synchronized...> other_side_id ,则执行如下逻辑 不太容易看懂,我们直接看代码实现 执行效果如下 我们分析下结果 tbl_follow_plus 只插入了一条记录 relation_ship...= 3 表示双向关注 tbl_friend 插入了一条记录 同时关注 这个业务就实现了 有小伙伴就有疑问了:楼主你只分析了 one_side_id 关注 other_side_id 的情况,
,事务被阻塞,为何我只锁住了index_id=5的记录,插入index_id=4的数据也插不进去了,难道是client1锁全表了么?...locks的范围也应该是(5,6]才对,即index_id=6的记录插不进去,但是index_id=5的记录应该可以差的进去,为何(priv_id=6,index_id=5)这条记录没有插进去呢?...即每一条辅助索引记录同样还包含主键。...=9)记录之间插入,由于为了防止幻读,为了不让满足index_id=6的记录再插入进去,因此那段区间就被加了锁,而不是别的区间。...6,5)顺利插入,这是因为client1仅仅对(7,6)这一条记录加了record lock,而不会对旁边区间加gap锁,这种情况下是会发生幻读现象的。
,相同的就错,我搜了一下网上,几乎没有过滤参数,可以用经典'or'='or'进去的,'xor都可以进去,大家可以尝试一下。..."源代码,从中找到后台登录的页面"login.asp"其中有以下一段代码: <% (1)pwd = request.form("pwd") "获取客户端输入的密码,再把值赋给pwd" (2)name...msg=您输入了错误的帐号或口令,请再次输入!"...,就交给了SQL语句查询,如果查询的记录是位于最后一条记录之前,刚设置Session变量UserName,PassWord的值分别为Name,pwd,并重定向到"Manage.asp". ...or真or假and假,通过简单的运算,则最终为真,而SQL语句的查询结果也变成真了,这样大家可能还不怎么听得懂,我换成另一条语句:1' or 1=1 or '1'='1,那么SQL语句就变成了sql
也就是说,这条记录即不是正常记录,也不是已删除记录。在删除语句所在的事务提交之前,被删除的记录一直都处于这种中间状态(其实主要是为了实现MVCC的功能才这样处理的)。...这种情况会频繁发生,也就会随着记录越插越多而产生越来越多的空间碎片。...只有当页面块满的时候,如果再插入一条新记录,无法分配一条完整的记录空间时,会先查看PAGE_GARBAGE的空间和剩余空间相加是否可以容纳这条新的记录,如果可以,InnoDB则会尝试重新组织页内的记录。...为什么TRX_UNDO_DEL_MARK_REC类型的undo日志保存旧记录的trx_id值和roll_pointer值?...我们先插入两条记录: BEGIN; # 显示开启一个事务,假设该事务的事务id为100 # 插入两条记录 INSERT INTO tb_user(id, name, city) VALUES(1, 'muse
这对于事务A来说,就很奇怪了,AUTO_INCREMENT的列,连续插入了两条记录,一条是4,接下来一条变成了6,就像莫名其妙的幻影。...即: (1)多个事务可以拿到一把S锁,读读可以并行; (2)而只有一个事务可以拿到X锁,写写/读写必须互斥; 共享/排它锁的潜在问题是,不能充分的并行,解决思路是数据多版本,具体思路在《InnoDB并发如此高...t where id>10; 事务B后执行,在10与20两条记录中插入了一行: insert into t values(11, xxx); 这里: (1)会使用什么锁?...,而MyISAM的索引和记录是分开存储的。...画外音: 为什么要阻止id=10的记录插入? 如果能够插入成功,头一个事务执行相同的SQL语句,会发现结果集多出了一条记录,即幻影数据。
脏读 所有事务都可以看到其他未提交事务的执行结果 不可重复读 同一个事务执行过程中,另外一个事务提交了新数据,因此本事务先后两次读到的数据结果会不一致 幻读 当事物A查询某一范围的数据时,另一个事务B又在该范围内插入了新行并作了提交...当v1=40的记录有多条的时候,插入的id值要小于其中的最大id值。则可以成功插入; 当插入右侧值的时候,即插入v1=50的时候,要求插入的id值要大于id=18的范围。...当v1=50的记录有多条的时候,插入的id值要大于其中的最小id值。则可以成功插入。 所以为什么RR隔离级别下并发性能会有所下降,就是因为存在间隙锁。...Dead lock: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象。...先删再插,两条insert当需要进行唯一性冲突检测时,需要先加一个S锁,也会产生死锁。 那么对应的解决死锁问题的关键就是:让不同的session加锁有次序。
即多个事务在同一个索引、同一个范围区间内插入记录时,如果插入的位置不冲突,则不会阻塞彼此; 举个例子:在可重复读隔离级别下,对PK ID为10-20的数据进行操作: 事务1在10-20的记录中插入了一行...: insert into table value(11, xx) 事务2在10-20的记录中插入了一行: insert into table value(12, xx) 由于两条插入的记录不冲突,所以会使用插入意向锁...即一个事务正在往表中插入记录时,其他事务的插入必须等待,以便第1个事务插入的行得到的主键值是连续的。 举个例子:在可重复读隔离级别下,PK ID为自增主键 表中已有主键ID为1、2、3的3条记录。...事务1插入了一行: insert into table value(‘aa’) 得到一条(4,’aa’)的记录,未提交; 此时,事务2中插入了一行: insert into table value(‘bb...举个例子: 假如数据库已有ID为1、6两条记录,现在想要在ID in (4,10)之间更新数据的时候,会加上间隙锁,锁住[4,5] [7,10] ,(不包含已有记录ID=5本身) 那么在更新ID=5的记录
不同的是,在一张表里面只能有一个主键,主键不能为空,但唯一索引可以有多个。唯一索引可以有一条记录为null。...于是现在有如下选择: 在id_card创建唯一索引 创建一个普通索引 假定业务代码已经确保不会写入重复身份证号,这两个选择逻辑上都是正确的。 性能优化角度考虑,选择唯一索引还是普通索引呢?...即读一条记录时,并非将该一个记录从磁盘读出,而以页为单位,将其整体读入内存。 所以普通索引,多了一次“查找和判断下一条记录”的操作,即一次指针寻找和一次计算。...本文前提是“业务代码已经保证不会写入重复数据”,才讨论性能问题。 如果业务不能保证或业务就是要求数据库来做约束 没得选,必须创建唯一索引。...如果没有复现,检查 隔离级别是不是RR(Repeatable Read,可重复读) 创建的表t是不是InnoDB引擎 为什么经过这个操作序列,explain的结果就不对了?
而当前读的规则,就是要能读到所有已经提交的记录的最新值。...T2 时刻,session B 事务提交,写入了两条语句; 2. T4 时刻,session C 事务提交,写入了两条语句; 3. ...5,10),而 session B 也是在这个间隙加的间隙锁,它们有共同的目标,即:保护这个间隙,不允许插入值,但是它们之间是不冲突的。...比如说,大家都用读提交,可是逻辑备份的时候,mysqldump 为什么要把备份线程设置成可重复读呢?...然后,在备份期间,备份线程用的是可重复读,而业务线程用的是读提交,同时存在两种事务隔离级别,会不会有问题?
而当前读的规则,就是要能读到所有已经提交的记录的最新值。...如果现在这样看感觉还不明显的话,我再往 session B 和 session C 里面分别加一条 SQL 语句,你再看看会出现什么现象。...T2 时刻,session B 事务提交,写入了两条语句; 2. T4 时刻,session C 事务提交,写入了两条语句; 3....比如说,大家都用读提交,可是逻辑备份的时候,mysqldump 为什么要把备份线程设置成可重复读呢?...然后,在备份期间,备份线程用的是可重复读,而业务线程用的是读提交,同时存在两种事务隔离级别,会不会有问题?
现有如下选择: 在id_card创建唯一索引 创建一个普通索引 假定业务代码已确保不会写入重复身份证号,这两个选择逻辑上都正确。 但性能角度考虑,选择哪个呢? 假设字段 k 上的值都不重复。...即读一条记录时,并非将该一个记录从磁盘读出,而以页为单位,将其整体读入内存。 所以普通索引,多了一次“查找和判断下一条记录”的操作,即一次指针寻找和一次计算。...该更新做了如下操作: Page1在内存,直接更新内存 Page2不在内存,就往change buffer区,缓存一个“往Page2插一行记录”的信息 将前两个动作记入redo log 至此,事务完成。...到底何时使用唯一索引 问题就在于“业务可能无法确保”,而本文前提是“业务代码已保证不会写入重复数据”,才讨论的性能问题。 若业务无法保证或业务就是要求数据库来做约束 没有撤退可言,必须创建唯一索引。...如果没有复现,检查 隔离级别是不是RR(Repeatable Read,可重复读) 创建的表t是不是InnoDB引擎 为什么经过这个操作序列,explain的结果就不对了?
日志记录不仅对于我们开发的应用,还是对于ASP.NET Core框架功能都是一项非常重要的功能特性。...创建一个Logger对象,我们利用后者写入了一条Information等级的日志。...我们运行程序之后利用浏览器访问目标地址后,宿主控制台上会出现如下图所示的三条日志。除了第二条日志是由我们自己编写的代码写入的之外,其余两条都是ASP.NET Core框架自己写入的。...但是这不是ASP.NET Core的问题,而是我们在调用LoggerFactory的扩展方法AddConsole注册ConsoleLoggerProvider的时候并未显式开启针对日志范围的支持。...在这种情况下,我们就需要使用记录的日志进行差错和纠错,因为ASP.NET Core在处理请求遇到的异常都会记录到日志中。
幻读的问题 语义问题 session A在T1时刻就声明了,“我要把所有d=5的行锁住,不准别的事务进行读写操作”。而实际上,这个语义被破坏了。...但id=1这一行,在DB里结果是(1,5,5),而根据binlog的执行结果是(1,5,100),即幻读依旧。 为何把所有记录都上锁了,还是阻止不了id=1这行的插入和更新?...即使把所有记录都加锁,还是阻止不了新插入的记录,这也是为什么“幻读”会被单独拿出来解决。 InnoDB解决幻读 幻读的原因 行锁只能锁行,但是新插入记录这个动作,要更新的是记录之间的“间隙”。...因为表t里并没c=7记录,因此session A加的间隙锁(5,10)。而session B也是在这个间隙加的间隙锁。它们有共同的目标,即:保护这个间隙,不允许插入值。但它们之间不冲突。...如果大家都用读提交,可是逻辑备份时,mysqldump为什么要把备份线程设置成可重复读? 然后,在备份期间,备份线程用的是可重复读,而业务线程用的是读提交。
数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;事务是一组不可再分割的操作集合(工作逻辑单元) 举个栗子: 事务最经典常用的栗子可能就是转账:一个账户少钱了,哪另一个账户肯定要多钱,李永龙说过...举个栗子: 假设某公司工资为10000的有10个人 1.事务1,读取所有工资为10000的员工,会读取到10条记录; 2.事务2此时向工资表中插入了一条员工记录,工资正好也是10000; 3.事务1再次读物所有工资为...不可重复读的重点是修改 : 同样的条件 , 你读取过的数据 , 再次读取出来发现值不一样了 幻读的重点在于新增或者删除 同样的条件 , 第 1 次和第 2 次读出来的记录数不一样 为了解决上边所说的几个问题...我不知道这个名字是怎么起的,为了增强大家的印象,可以这么想,这个事务好轻浮啊,饥渴到连别人没提交的东西都等不及,真脏,呸! 实际上我们的数据改变了吗?...结果,问题产生了,竟然插不进去 结论 此处需要注意的是,因为我们使用的Innodb引擎,所以此处不会产生幻读,其他引擎的话在这个隔离级别可能会产生幻读(至于为什么说Innodb不会,且听下回分解,其实MySQL
我们敲代码的,不就是要多考虑这些正常流程之外的“小概率事件”吗,只写正常流程,谁都会写。 根据官方的说法,消息重复会发生在这些场景中: 发送时消息重复。...我还是需要数据库通过唯一索引来帮我保证只有一条数据被成功落库,所以我想着抽一个专门的表出来,比如叫做消息消费记录表。 只要数据插入了这个表,就代表消息被消费了。后续即使重发,也不会插入成功。...而 MQ 没有收到这个消息的回执,也会再次进行投递。 由于消息消费记录表里没有这个数据,所以会再次进行消费。 在上面的这个过程中,MQ 再次投递,是为了 at least once。...而我们引入了消息消费记录表,通过唯一索引来保证不重复消费,这个玩意加上 at least once,在业界有另外一个叫法:exactly-only。...于是我手动写了这样的一坨代码,四处散落在我写的模块里面。 后来一个师兄看了我的代码,提出了应该用事务来保证这样的逻辑,并给我做了演示,我才去了解了事务相关的东西。
下面是我跟小王的主要对话。 我:说说怎么了? 小王:我将记录接口日志的功能放到了每个controller中,现在感觉有点繁琐,我这样做是不是不太合适? 我:为什么要去每个接口里记录日志?...小王:最开始我是用的拦截器,但是这样一个请求就记录了两条记录。 我:为什么是两条? 小王:在preHandle中记录一条请求数据,在postHandle中记录一条响应数据。 我:。。。...你不是说你会Aop吗? 小王:Aop也是一样,在前置通知记录一条请求数据,后置通知记录一条响应数据。...小王:这个数据和以前记录操作日志的不太一样,以前只需要在前置通知记录一条操作日志就可以了,但是现在有响应,所以只能在controller中记录日志了。 我:那你知不知道有个环绕通知?...) 异常通知:在我们的目标方法出现异常后运行(@AfterThrowing) 环绕通知:目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法,joinPoint.procced()就是执行目标方法的代码
不同的是,在一张表里面只能有一个主键,主键不能为空,唯一索引可以有多个,唯一索引可以有一条记录为空,即保证跟别人不一样就行。...于是现有俩选择: 给id_card字段创建唯一索引 创建一个普通索引 假定业务代码已保证不会写入重复的身份证号,这两个选择逻辑上都正确。但从性能角度考虑,唯一索引还是普通索引呢?...即读一条记录时,并非将该一个记录从磁盘读出,而以页为单位,将其整体读入内存。 因此普通索引,要多做一次“查找和判断下一条记录”的操作,也就一次指针寻找和一次计算。...本文前提是“业务代码已经保证不会写入重复数据”下,讨论性能问题。 如果业务不能保证,或者业务就是要求数据库来做约束,那么没得选,必须创建唯一索引。...如果没有复现,检查 隔离级别是不是RR(Repeatable Read,可重复读) 创建的表t是不是InnoDB引擎 为什么经过这个操作序列,explain的结果就不对了?
或许此时你已经对于为什么多人调试程序时数据库访问不时出现卡顿有了一些自己的想法,当然这只是锁机制的冰山一角。...在这个例子当中,线程A的事务和线程B的事物分别占有id=1和id=2这两条记录的写锁,使得两个线程在试图获取其他线程占用的锁资源时陷入死锁。...而InnoDB存储引擎默认的事务隔离级别是可重复读(Read Repeatable),简单来说:就是当事务A启动期间,普通的select查询将无法访问到其他事务在此期间对表记录的改动。...上面讲解死锁检测的时候我用更新语句获得了行记录的写锁,而这里,通过增加for update后缀,可以使得当前读操作也获取行记录的写锁。...• 此时事务B并发插入了一条(2,1)的记录,并且成功。 • 事务A的第二个sql依旧查询c=1的记录,获得(1,1)、(2,1)两条记录,从语义上违背了第一条sql的目的。
所以学一个知识,我总在想有没有那样一个万变不离其宗的底层知识,我掌握了它便能一通百通,相关问题我就都会了,比如面试官问这些问题: 写线程操作一条数据,另外一个读线程也在读取这条数据,写线程还没有提交事务...是不是感觉自己离三万月薪还差一点? 同样关于网络的知识也是如此,面试时会经常被人问到三次握手、四次挥手的过程。 那到底三次握手、四次挥手是为了什么? 为什么是三次握手、四次挥手?...即ACID。另外,原子性、隔离性、持久性最终都是为了一致性,一致性是事务的最终目的。 我们先总体上看一条更新类型的SQL语句它的内部执行流程,然后再跟进去学习每一个细节知识点。...当MySQL执行一条更新语句的时候,InnoDB引擎会把记录先写到redo log文件中,并更新内存。...binlog日志是持续追加写入的,不存在被覆盖一说。 binlog有两种模式,statement 格式的话是记sql语句, row格式会记录行的内容,记两条,更新前和更新后。
其实可以这么理解,发布/订阅模型等于我们都加入了一个群聊中,我发一条消息,加入了这个群聊的人都能收到这条消息。...小结一下 队列模型每条消息只能被一个消费者消费,而发布/订阅模型就是为让一条消息可以被多个消费者消费而生的, 当然队列模型也可以通过消息全量存储至多个队列来解决一条消息被多个消费者消费问题,但是会有数据的冗余...因此还是看业务,例如日志的传输可能丢那么一两条关系不大,因此没必要等消息刷盘再响应。 如何处理重复消息 我们先来看看能不能避免消息的重复。...或者记录关键的key,比如处理订单这种,记录订单ID,假如有重复的消息过来,先判断下这个ID是否已经被处理过了,如果没处理再进行下一步。当然也可以用全局唯一ID等等。...因此我们需要先定位消费慢的原因,如果是bug则处理 bug ,如果是因为本身消费能力较弱,我们可以优化下消费逻辑,比如之前是一条一条消息消费处理的,这次我们批量处理,比如数据库的插入,一条一条插和批量插效率是不一样的
领取专属 10元无门槛券
手把手带您无忧上云