我在使用数据库触发器时遇到问题,该触发器记录在表上执行的所有查询,当该查询包含4字节UTF-8字符时。
在Ubuntu 16.04上,mysql版本是5.7.19
示例脚本:
show variables where Variable_name like 'character\_set\_%' or Variable_name like 'collation%';
drop database if exists my_test_db;
create database my_test_db;
use my_test_db;
create table my_test_table(id int not null primary key auto_increment, jdoc json not null);
create table my_test_table_log(id int not null primary key auto_increment, query varchar(1024) NOT NULL);
SELECT "insert works when trigger is not active" as "";
insert into my_test_table(jdoc) VALUES(JSON_OBJECT("Dubai was", ""));
DELIMITER |
CREATE TRIGGER log_my_test_table_queries_insert
BEFORE INSERT ON `my_test_table`
FOR EACH ROW
BEGIN
DECLARE original_query VARCHAR(1024);
SET original_query = (SELECT info
FROM INFORMATION_SCHEMA.PROCESSLIST
WHERE id = CONNECTION_ID());
INSERT INTO `my_test_table_log` (`query`) VALUES (original_query);
END;
|
DELIMITER ;
SELECT "insert doesn't work when trigger is active" as "";
insert into my_test_table(jdoc) VALUES(JSON_OBJECT("Dubai was", ""));
我的输出:
+--------------------------+--------------------+
| Variable_name | Value |
+--------------------------+--------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| collation_connection | utf8mb4_unicode_ci |
| collation_database | utf8mb4_unicode_ci |
| collation_server | utf8mb4_unicode_ci |
+--------------------------+--------------------+
10 rows in set (0.00 sec)
Query OK, 2 rows affected (0.03 sec)
Query OK, 1 row affected (0.00 sec)
Database changed
Query OK, 0 rows affected (0.03 sec)
Query OK, 0 rows affected (0.02 sec)
+-----------------------------------------+
| |
+-----------------------------------------+
| insert works when trigger is not active |
+-----------------------------------------+
1 row in set (0.00 sec)
Query OK, 1 row affected (0.00 sec)
Query OK, 0 rows affected (0.01 sec)
+--------------------------------------------+
| |
+--------------------------------------------+
| insert doesn't work when trigger is active |
+--------------------------------------------+
1 row in set (0.01 sec)
ERROR 1366 (HY000): Incorrect string value: '\xF0\x9F\x94\xA5")...' for column 'INFO' at row 1
数据库似乎是使用正确的字符集
创建的SHOW CREATE TRIGGER log_my_test_table_queries_insert;
SHOW CREATE TABLE my_test_table;
SHOW CREATE TABLE my_test_table_log;
detailsdetailsdetails
答案 0 :(得分:2)
这是因为information_schema.processlist
正在使用UTF8mb3字符集。 (UTF是UTFmb3的别名)。这个简单的查询说明了这一点:
mysql> select info, "" from information_schema.processlist;
+------------------------------------------------------+------+
| info | ? |
+------------------------------------------------------+------+
| select info, "?" from information_schema.processlist | |
+------------------------------------------------------+------+
1 row in set, 1 warning (0,00 sec)
Warning (Code 1366): Incorrect string value: '\xF0\x9F\x94\xA5" ...' for column 'INFO' at row 1
当触发器尝试将info
列的内容插入另一个表时,上述警告可能会导致错误。
我认为问题是查询字符串按原样存储在processlist
表中,而不将其转换为预期的字符集。我已就此提出bug report。
答案 1 :(得分:0)
做这些
SHOW CREATE TRIGGER log_my_test_table_queries_insert;
SHOW CREATE TABLE my_test_table;
SHOW CREATE TABLE my_test_table_log;
我怀疑你会发现它们是使用错误的字符集创建的。
更改这一行可能就足够了:
create database my_test_db CHARACTER SET utf8mb4;
(我无法重现你的测试用例的问题。你使用的是什么版本的MySQL或MariaDB?)