我正在将应用程序从 MariaDB 版本 5.5 迁移到版本 10.3。 该应用程序使用 handler open、handler read 命令直接访问数据库中的 MyISAM 表。还有另一个应用程序从不同的连接对相同的表进行操作,它使用标准的选择/插入/更新等语句。
在 5.5 版本中,处理程序 open 命令不会在表上放置任何锁,但在 10.3 中,它的作用如下;-
MariaDB [test]> create table t1 (a int) engine=MyISAM ;
Query OK, 0 rows affected (0.003 sec)
MariaDB [test]> handler t1 open ;
Query OK, 0 rows affected (0.001 sec)
MariaDB [test]> select * from information_schema.metadata_lock_info ;
+-----------+-----------------+---------------+---------------------+--------------+------------+
| THREAD_ID | LOCK_MODE | LOCK_DURATION | LOCK_TYPE | TABLE_SCHEMA | TABLE_NAME |
+-----------+-----------------+---------------+---------------------+--------------+------------+
| 17821 | MDL_SHARED_READ | NULL | Table metadata lock | test | t1 |
+-----------+-----------------+---------------+---------------------+--------------+------------+
1 row in set (0.001 sec)
当另一个连接尝试
lock tables t1 write ;
命令时,它会无限期阻止。
在进程列表中,连接将显示“等待表元数据锁定”。
MySQL 手册中的处理程序页面https://dev.mysql.com/doc/refman/8.0/en/handler.html 说;-
HANDLER 是一个比较低级的语句。例如,它不提供一致性。也就是说,HANDLER ... OPEN 不会拍摄表的快照,并且不会锁定表。这意味着发出 HANDLER ... OPEN 语句后,可以修改表数据(由当前会话或其他会话),并且这些修改可能仅对 HANDLER ... NEXT 或 HANDLER ... PREV 扫描部分可见。
这就是 MariaDB 5.5 过去的行为方式。然而,MariaDB 的手册页(https://mariadb.com/kb/en/handler-commands/)暗示没有元数据锁定;-
限制 由于这是存储引擎的直接接口,因此您可以执行的操作以及表更改时会发生什么情况可能会受到一些限制。
(显然,如果表已被锁定,则无法更改)。
处理程序 open 命令在表上放置的表元数据锁似乎破坏了以前版本的功能。应该放那把锁吗?
锁定表写入 “独占写锁。没有其他连接可以读取或写入此表”
这意味着当
HANDLER tbl OPEN
存在时,LOCK TABLES
无法继续,因为 HANDLER tbl OPEN 可以读取它。所以它必须等待或出错。
之前的 5.5 行为将违反此排他性。