アーカイブ「2024年09月」

MariaDBの同一ホスト間のデータ同期システムとして作っていたmagentadeskなのですが、

0.7.0のリリースで、MySQL 8.0.31 と 8.0.32 の対応を入れました。

https://github.com/shigenobu/magentadesk

なんで今までやらなかったかというと、

  • テーブルの解析でのinformation_schemaの格納のされ方が微妙にMariaDBとMySQLで異なる
  • MySQLではEXCEPTが8.0.31までなかった
  • MariaDBのdynamic columnに相当する機能がMySQLでは賄えるか不安だった
  • シーケンスがないのをどうするか

といったところでしたが、MySQL 8.0.31でEXCEPTが入ったので、

本腰入れて対応してみました。

やってみて色々大変でした。

なかでもUNIONの動作がおかしくて、無理やりやる感じでした。

MariaDBとMySQLでのUNIONの動作を見てみます。


まず以下のデータを用意します。

> select * from base;
+------+
| c    |
+------+
|    1 |
|    2 |
+------+

> select * from compare;
+------+
| c    |
+------+
|    1 |
|    3 |
+------+

次にこんなSQLを投げます。

with 
t1 as 
(
  select * from base
  except
  select * from compare
),
t2 as 
(
  select * from compare
  except
  select * from base
),
tt1 as 
(
  select 
  json_object('c', t1.c) as b,
  json_object('c', t2.c) as c
  from
  t1
  left outer join
  t2
  on t1.c = t2.c
),
tt2 as 
(
  select 
  json_object('c', t1.c) as b,
  json_object('c', t2.c) as c
  from
  t1
  right outer join
  t2
  on t1.c = t2.c
),
t as 
(
  select * from tt1
  union
  select * from tt2
)
select * from t;

ちょっとややこしいのですが、

MariaDBとMySQLの結果を見てみます。

(MariaDB)

+-------------+-------------+
| b           | c           |
+-------------+-------------+
| {"c": 2}    | {"c": null} |
| {"c": null} | {"c": 3}    |
+-------------+-------------+

(MySQL)

+-------------+-------------+
| b           | c           |
+-------------+-------------+
| {"c": 2}    | {"c": null} |
| {"c": 1}    | {"c": 1}    |
| {"c": null} | {"c": 3}    |
+-------------+-------------+

いやー、MySQLの結果がおかしいですよね。これ仕様なのか?

EXCEPTで除いている筈なのに。。

MySQLのUNIONは結構昔から不具合あるようで、

なんかこうなってくると複雑な集計クエリーを投げるのがちょっと怖い感じもしますね。

現状では、気をつけましょうとしかいいようがないですが。。

以上

投稿日時:2024年09月26日 00:43   カテゴリー:java, mariadb, mysql   [コメントがあればどうぞ]

Rolling release(つまりSTS)なのですが、2024年8月にMariaDB11.5がGAになりました。

(参考)

https://mariadb.com/kb/en/changes-improvements-in-mariadb-11-5

気になっていたtimestamp拡張が入り、

2106-02-07 06:28:15 UTC

までtimestampを扱えるようになりました。

実際に、10.11と11.5で比較してみました。

なお、timezoneは日本にしています。


MariaDB 10.11

-- int max
> set timestamp = 2147483647; select now();
Query OK, 0 rows affected (0.000 sec)

+---------------------+
| now()               |
+---------------------+
| 2038-01-19 12:14:07 |
+---------------------+
-- int max + 1
> set timestamp = 2147483648; select now();
ERROR 1231 (42000): Variable 'timestamp' can't be set to the value of '2147483648'
+---------------------+
| now()               |
+---------------------+
| 2038-01-19 12:14:07 |
+---------------------+
-- unsigned int max
> set timestamp = 4294967295; select now();
ERROR 1231 (42000): Variable 'timestamp' can't be set to the value of '4294967295'
+---------------------+
| now()               |
+---------------------+
| 2038-01-19 12:14:07 |
+---------------------+
-- unsigned int max + 1
> set timestamp = 4294967296; select now();
ERROR 1231 (42000): Variable 'timestamp' can't be set to the value of '4294967296'
+---------------------+
| now()               |
+---------------------+
| 2038-01-19 12:14:07 |
+---------------------+

見てもらえればわかりますが、

2038-01-19 12:14:07

が限界となっています。


MariaDB 11.5

-- int max
> set timestamp = 2147483647; select now();
Query OK, 0 rows affected (0.001 sec)

+---------------------+
| now()               |
+---------------------+
| 2038-01-19 12:14:07 |
+---------------------+
-- int max + 1
> set timestamp = 2147483648; select now();
Query OK, 0 rows affected (0.001 sec)

+---------------------+
| now()               |
+---------------------+
| 2038-01-19 12:14:08 |
+---------------------+

この時点で、超えましたね。

-- unsigned int max
> set timestamp = 4294967295; select now();
Query OK, 0 rows affected (0.001 sec)

+---------------------+
| now()               |
+---------------------+
| 2106-02-07 15:28:15 |
+---------------------+
-- unsigned int max + 1
> set timestamp = 4294967296; select now();
Query OK, 0 rows affected, 1 warning (0.001 sec)

+---------------------+
| now()               |
+---------------------+
| 2106-02-07 15:28:15 |
+---------------------+

> show warnings;
+---------+------+---------------------------------------------------+
| Level   | Code | Message                                           |
+---------+------+---------------------------------------------------+
| Warning | 1292 | Truncated incorrect timestamp value: '4294967296' |
+---------+------+---------------------------------------------------+

unsigned int の最大値を超えるとwaningはでましたが、

2106-02-07 15:28:15

まで最大値が伸びているようです。


そもそも、timestampをunsignedにしたというのは、ドライバー影響を抑えるという名目だったかなと。

で、実際に以下のようにデータを入れてみます。

CREATE TABLE `t1` (
  `c1` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
insert into t1 values ('2106-02-07 15:28:15');
> select * from t1;
+---------------------+
| c1                  |
+---------------------+
| 2106-02-07 15:28:15 |
+---------------------+

これをPHPとC#(mysqlconnector)で取得してみたところ、

2106-02-07 15:28:15

が取得できることは確認できました。

MySQL側も同様の対応をしてくれると嬉しいです。

以上

投稿日時:2024年09月26日 00:18   カテゴリー:mariadb   [コメントがあればどうぞ]