mysql事务 可见性_一个Innodb 事务可见性问题-阿里云开发者社区

显然,满足以下三个条件的任意一个是,都会被阻塞住:

1、prebuilt->row_read_type != ROW_READ_TRY_SEMI_CONSISTENT  //以上三例都是1,都不满足

2、unique_search  //检索元组具有唯一性

3、index != clust_index //当前检索记录使用的索引不是聚集索引

当使用非索引列检索时,三者皆不满足;

当使用二级索引列检索时,满足index != clust_index

当使用聚集索引列检索时,满足unique_search

如果无需goto lock_wait_or_error, 就会去构建对应记录的最老版本(row_sel_build_committed_vers_for_mysql),对于插入而言,显然最老版本就是NULL空指针了,因此如果根据非索引列检索,Session 2就好像看不到那条记录一样,直接返回了。

如果表上没有索引的话,那么对于任意插入的记录,更新操作都见不到插入的记录(但是会为插入操作创建记录锁)。

我们再来看另外一种情况:

SESSION 1:

CREATE TABLE t1 (c1 int primary key , c2 int, c3 int, key(c2));

INSERT INTO t1 VALUES (1,2,3);

BEGIN;

UPDATE t1 SET c3 = c3 +1  WHERE c1 = 1;   // c3 from 3=>4

UPDATE t1 SET c3 = c3 +1  WHERE c1 = 1;   // c3 from 4=>5

SESSION 2:

UPDATE t1 SET c3=c3+1 WHERE c3 = 4;   // No block

UPDATE t1 SET c3=c3+1 WHERE c3 = 5;  // No block

UPDATE t1 SET c3=c3+1 WHERE c3 = 3;  //阻塞住

实际上我们通过semi consistent read 能读到最老版本的记录时会将prebuilt->row_read_type从ROW_READ_TRY_SEMI_CONSISTENT修改成ROW_READ_DID_SEMI_CONSISTENT。

当读完记录后,返回Server层,会判断是否进行了semi consistent read。如果该记录符合查询,并且进行了semi consistent read,那么就再读该记录,第二次再读时,如果SESSION1还没提交,就会进入锁等待,被阻塞住。如果记录不符合查询,那么就直接忽略掉。

在上述的3条SQL中,第一条和第二条构建的最老版本记录,都不满足c3=4 和c3=5,因此忽略掉,不阻塞。但是最老记录满足c3 =3 ,因此在第二次进入innodb层时被阻塞住。

相关代码(sql_update.cc,  mysql_update函数)

684        while (!(error=info.read_record(&info)) && !thd->killed)

685        {

686          thd->inc_examined_row_count(1);

687          bool skip_record= FALSE;

688          if (qep_tab.skip_record(thd, &skip_record))

689          {

690            error= 1;

691            /*

692             Don’t try unlocking the row if skip_record reported an error since

693             in this case the transaction might have been rolled back already.

694            */

695            break;

696          }

697          if (!skip_record)

698          {

699            if (table->file->was_semi_consistent_read())

700              continue; /* repeat the read of the same row if it still exists */

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值