OceanBase 数据库 MySQL 模式和 MySQL 数据库在显式加行锁的时候表现行为是不同的。OceanBase 数据库 MySQL 模式的锁机制与 Oracle 模式的锁机制是基本相同的,Oracle 没有范围锁,因此 OceanBase 数据库也没有范围锁。
OceanBase 数据库 MySQL 模式下加锁对外表现形式完全不同于 MySQL 数据库。
OceanBase 数据库严格按照读时间戳(snapshot)与 MVCC 数据的 commit 版本号来比较可以看到的数据版本,如果存在未提交的数据或者数据的 commit 版本号比读时间戳新,则不满足读取的要求,因此 OceanBase 数据库不会去尝试锁其他事务里还未提交的行数据。
MySQL 数据库在可重复读(RR)隔离级别下,会根据范围锁来判断等锁与加锁的记录范围,如果未提交的数据在读取范围内,则需要等待其提交完成。
以下示例清楚的展示了这两种不同的加锁行为。
OceanBase MySQL 模式
Session 1:开启事务,向表 t1 插入一行记录,但未提交。
obclient [(none)]> use db_mysql
Database changed
obclient [db_mysql]> select * from t1;
+----+------------+
| id | log_date |
+----+------------+
| 1 | 2023-06-30 |
| 2 | 2023-06-30 |
| 3 | 2023-02-15 |
+----+------------+
3 rows in set (0.013 sec)
obclient [db_mysql]> begin;
Query OK, 0 rows affected (0.001 sec)
obclient [db_mysql]> insert into t1 values (4,current_date());
Query OK, 1 row affected (0.020 sec)
Session 2:显式加行锁立即返回。
obclient [(none)]> use db_mysql
Database changed
obclient [db_mysql]> select * from t1 for update;
+----+------------+
| id | log_date |
+----+------------+
| 1 | 2023-06-30 |
| 2 | 2023-06-30 |
| 3 | 2023-02-15 |
+----+------------+
3 rows in set (0.024 sec)
MySQL V8.x
Session 1:开启事务,向表 t1 插入一行记录,但未提交。
mysql> use db_mysql
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select * from t1;
+----+------------+
| id | log_date |
+----+------------+
| 1 | 2023-02-28 |
| 2 | 2023-02-27 |
| 3 | 2023-02-15 |
+----+------------+
3 rows in set (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t1 values (4,current_date());
Query OK, 1 row affected (0.00 sec)
Session 2:显式加行锁超时报错,加锁失败。
mysql> use db_mysql
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select @@innodb_lock_wait_timeout;
+----------------------------+
| @@innodb_lock_wait_timeout |
+----------------------------+
| 10 |
+----------------------------+
1 row in set (0.00 sec)
mysql> select * from t1 for update;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
适用版本
OceanBase 数据库 V2.x 和 V3.x 版本。