函数lock_mode_stronger_or_eq 锁权限等级
row代表lock HashTable的权限
column代表预加锁的权限
ulint lock_mode_stronger_or_eq( /*=====================*/ enum lock_mode mode1, /*!< in: lock mode */ //找到的lock本身锁的模式 enum lock_mode mode2) /*!< in: lock mode */ //预加锁的模式 { ut_ad(mode1 == LOCK_X || mode1 == LOCK_S || mode1 == LOCK_IX || mode1 == LOCK_IS || mode1 == LOCK_AUTO_INC); ut_ad(mode2 == LOCK_X || mode2 == LOCK_S || mode2 == LOCK_IX || mode2 == LOCK_IS || mode2 == LOCK_AUTO_INC); return((LOCK_MODE_STRONGER_OR_EQ) & LK(mode1, mode2)); }
IS IX S X AI
IS + - - - -
IX + + - - -
S + - + - -
X + + + + +
AI - - - - +
Innodb的锁分基础锁和精准锁
IS 意向共享锁 只针对于 表
IX 意向排它锁 只针对于 表
S 共享锁 针对于 表、记录
X 排它锁 针对于 表、记录
+ 代表row锁的强度>=column锁
/////////////////////////////////////////////////////////////////////////////////////////////////////
#define LOCK_MODE_STRONGER_OR_EQ 0
这里的 0 是int类型,占4(字节)*8(位)=32位,即下标从0到31
#define LK(a,b) (1 << ((a) * LOCK_NUM + (b)))
这个宏里LOCK_NUM 为6,不是5
之所以为6,是要保证LK()的结果 不能超过31,同时保证为最大的数,我想应该是避免冲突吧
例如, 使用 LOCK_AUTO_INC 为 4,如果 LOCK_NUM 为5的话
1<<(4*5+4)=2^24
可理解为数字 1 左移24位
如果 LOCK_NUM 为6
1 << (4*6+4) = 2^28
可理解为数字 1 左移 28位
LOCK_NUM 大于6就不行了,例如
1<<(4*7+4)=2^32
可理解为 数字 1 左移 32位,超过int 类型最大下标 31 了, 会溢出的
即 #define LK(a,b) (1 << ((a) * 6 + (b)))
/////////////////////////////////////////////////////////////////////////////////////////////////////
#define LOCK_MODE_STRONGER_OR_EQ 0 \
| LK(LOCK_IS, LOCK_IS) \
| LK(LOCK_IX, LOCK_IS) | LK(LOCK_IX, LOCK_IX) \
| LK(LOCK_S, LOCK_IS) | LK(LOCK_S, LOCK_S) \
| LK(LOCK_AUTO_INC, LOCK_AUTO_INC) \
| LK(LOCK_X, LOCK_IS) | LK(LOCK_X, LOCK_IX) | LK(LOCK_X, LOCK_S) \
| LK(LOCK_X, LOCK_AUTO_INC) | LK(LOCK_X, LOCK_X)
这个宏里每一个LK(a,b)就代表了row锁的强度>=column锁 这个 组合 在32位中的下标
当这些组合经过 | 或运算,组成一个int类型的数字
那么当要检查某个组合是否是强度大的锁组合时,只需要跟上面的数 进行 & 与运算(全1为1,其他为0)即可