Since I need several mediumtext fields I need the barracuda file format. There are many articales and videos on how to convert an existing antelope table to barracuda but none on how to create a new table using barracuda. Is there an easy to do this with MariaDB? I'd like to use a docker container if possible.
It's messy in 5.6 (MariaDB 10.0 and 10.1):
SET GLOBAL innodb_file_format=Barracuda;
SET GLOBAL innodb_file_per_table=1;
SET GLOBAL innodb_large_prefix=1; -- optional (if you also need wide indexes)
ALTER TABLE tbl ROW_FORMAT=DYNAMIC;
It's possibly defaulted correctly in 5.7 (MariaDB 10.2).
Try:
MariaDB [_]> SELECT VERSION();
+-----------------+
| VERSION() |
+-----------------+
| 10.1.23-MariaDB |
+-----------------+
1 row in set (0.00 sec)
MariaDB [_]> SHOW VARIABLES LIKE 'innodb_file_format';
+--------------------+----------+
| Variable_name | Value |
+--------------------+----------+
| innodb_file_format | Antelope |
+--------------------+----------+
1 row in set (0.01 sec)
MariaDB [_]> CREATE TABLE `barracuda_table` (`col` MEDIUMTEXT) ROW_FORMAT=DYNAMIC;
Query OK, 0 rows affected, 2 warnings (0.00 sec)
MariaDB [_]> SHOW WARNINGS;
+---------+------+--------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------------------------------+
| Warning | 1478 | InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope. |
| Warning | 1478 | InnoDB: assuming ROW_FORMAT=COMPACT. |
+---------+------+--------------------------------------------------------------------+
2 rows in set (0.00 sec)
MariaDB [_]> SELECT ROW_FORMAT
-> FROM `information_schema`.`tables`
-> WHERE `TABLE_SCHEMA` = DATABASE() AND
-> `TABLE_NAME` = 'barracuda_table';
+------------+
| ROW_FORMAT |
+------------+
| Compact |
+------------+
1 row in set (0.00 sec)
MariaDB [_]> DROP TABLE `barracuda_table`;
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> SET ##GLOBAL.innodb_file_format = 'Barracuda';
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> SHOW VARIABLES LIKE 'innodb_file_format';
+--------------------+-----------+
| Variable_name | Value |
+--------------------+-----------+
| innodb_file_format | Barracuda |
+--------------------+-----------+
1 row in set (0.00 sec)
MariaDB [_]> CREATE TABLE `barracuda_table` (`col` MEDIUMTEXT) ROW_FORMAT=DYNAMIC;
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> SELECT ROW_FORMAT
-> FROM `information_schema`.`tables`
-> WHERE `TABLE_SCHEMA` = DATABASE() AND
-> `TABLE_NAME` = 'barracuda_table';
+------------+
| ROW_FORMAT |
+------------+
| Dynamic |
+------------+
1 row in set (0.00 sec)
MariaDB [_]> SELECT `NAME`, `FILE_FORMAT`, `ROW_FORMAT`
-> FROM `information_schema`.`INNODB_SYS_TABLES`
-> WHERE `NAME` = '_/barracuda_table';
+-------------------+-------------+------------+
| NAME | FILE_FORMAT | ROW_FORMAT |
+-------------------+-------------+------------+
| _/barracuda_table | Barracuda | Dynamic |
+-------------------+-------------+------------+
1 row in set (0.00 sec)
See XtraDB/InnoDB Storage Formats.
Related
In Unicode Locale Data Markup Language(LDML), since version 24, the element and its sub-elements is deprecated. But the MySQL example still uses deprecated element.
The collation defined when I added to MySQL Collation with a latest version of the CLDR Collation definition marked with the element did not take effect.
I want to add to MySQL collation for the UTF8 character using stroke collation in <zh.xml>.
MySQL Path: mysql-8.0.28-winx64\share\charsets\index.xml
MySQL version: 8.0.28
Stroke collation in: https://github.com/unicode-org/cldr/blob/main/common/collation/zh.xml
http://www.unicode.org/reports/tr35/#Element_rules
https://dev.mysql.com/doc/mysql-g11n-excerpt/8.0/en/ldml-rules.html
How to repeat
Step 1. Edit mysql-8.0.28-winx64\share\charsets\index.html
Add some element(collation content copy from CLDR collation zh.xml) like:
<charset name="utf8mb4">
<family>Unicode</family>
<description>UTF-8 Unicode</description>
<collation name="utf8mb4_stroke_ci" id="1030" type='stroke'>
<cr><![CDATA[
[import zh-u-co-private-pinyin]
...more data...
]]></cr>
</collation>
</charset>
Step 2. Restart mysql server
Step 3. Check collation added success
mysql> SHOW COLLATION WHERE Collation = 'utf8mb4_stroke_ci';
+----------------+---------+------+---------+----------+---------+---------------+
| Collation | Charset | Id | Default | Compiled | Sortlen | Pad_attribute |
+----------------+---------+------+---------+----------+---------+---------------+
| utf8mb4_stroke_ci | utf8 | 1030 | | | 8 | PAD SPACE |
+----------------+---------+------+---------+----------+---------+---------------+
1 row in set (0.00 sec)
Step 4. Create a database and table then insert some data
mysql> create database collation_test;
Query OK, 1 row affected (0.02 sec)
mysql> use collation_test;
Database changed
mysql> SET NAMES utf8mb4 COLLATE utf8mb4_stroke_ci;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE member_stroke (
-> name VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_stroke_ci
-> );
Query OK, 0 rows affected (0.05 sec)
mysql> insert into member_stroke values('一'); -- character '一' means '1', stroke 1.
Query OK, 1 row affected (0.01 sec)
mysql> insert into member_stroke values('二'); -- character '一' means '2', stroke 2.
Query OK, 1 row affected (0.01 sec)
mysql> insert into member_stroke values('三'); -- character '一' means '3', stroke 3.
Query OK, 1 row affected (0.01 sec)
Step 4. Select data and order by name
mysql> select * from member_stroke order by name;
+------+
| name |
+------+
| 一 |
| 三 |
| 二 |
+------+
3 rows in set (0.00 sec)
Expect result
+------+
| name |
+------+
| 一 |
| 二 |
| 三 |
+------+
Additional information
When I use the element to define collation, it success! But is`s deprecated at LDML(version 24) on 2013-09-18.
<charset name="utf8mb4">
<family>Unicode</family>
<description>UTF-8 Unicode</description>
<collation name="utf8mb4_stroke_ci" id="1030" type='stroke' alt='short'>
<rules>
<!-- START AUTOGENERATED STROKE SHORT -->
<reset><last_non_ignorable /></reset>
<p>⠁</p><!-- INDEX 1 -->
<pc>一</pc><!-- 1 -->
<p>⠁</p><!-- INDEX 2 -->
<pc>二</pc><!-- 2 -->
<p>⠁</p><!-- INDEX 3 -->
<pc>三</pc><!-- 3 -->
</rules>
</collation>
</charset>
mysql> select * from member_stroke order by name;
+------+
| name |
+------+
| 一 |
| 二 |
| 三 |
+------+
3 rows in set (0.00 sec)
I have to extract data from a MariaDB database where the owners have stored JSON data in varchar fields in the form:
[-100, -18.3, -10.1, 2.2, 5.8, ...]
I would like to be able to select individual entries from each of these JSON encoded text fields.
I have been reading about the many features of JSON support in MariaDB and I have looked at many examples of how data can be stored as JSON in text fields, but they all would require changes to how the data is inserted and/or the schema.
I cannot change the DB in any way. I have ReadOnly access.
The owners of the DB are currently using MariaDB 10.0, but I may be able to get them to upgrade to 10.1
In short, given the following (very simple example), how can I select the 2nd element in the ‘data’ field?
I assume using the JSON features is the way to go (given all the data is JSON), but is there another way? Performance isn't all that important.
MariaDB [mtest]> show columns from cal from mtest;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| data | varchar(255) | YES | | NULL | |
+-------+--------------+------+-----+---------+-------+
1 row in set (0.00 sec)
MariaDB [mtest]> select * from cal;
+---------+
| data |
+---------+
| [10.1,12.0,16.78,18.9] |
+---------+
1 row in set (0.00 sec)
If you can upgrade to 10.1 (from MariaDB 10.1.9) via CONNECT can use JsonGet_Real function.
Try:
MariaDB [_]> SELECT VERSION();
+-----------------+
| VERSION() |
+-----------------+
| 10.1.14-MariaDB |
+-----------------+
1 row in set (0.00 sec)
MariaDB [_]> INSTALL SONAME 'ha_connect';
Query OK, 0 rows affected (0.01 sec)
MariaDB [_]> CREATE FUNCTION `jsonget_real` RETURNS REAL SONAME 'ha_connect.so';
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> DROP TABLE IF EXISTS `cal`;
Query OK, 0 rows affected, 1 warning (0.01 sec)
MariaDB [_]> CREATE TABLE IF NOT EXISTS `cal` (
-> `data` VARCHAR(255)
-> );
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> INSERT INTO `cal`
-> (`data`)
-> VALUES
-> ('[10.1,12.0,16.78,18.9]');
Query OK, 1 row affected (0.00 sec)
MariaDB [_]> SELECT `data` FROM `cal`;
+------------------------+
| data |
+------------------------+
| [10.1,12.0,16.78,18.9] |
+------------------------+
1 row in set (0.00 sec)
MariaDB [_]> SELECT `jsonget_real`(`data`, '[1]', 2) FROM `cal`;
+--------------------------------+
| jsonget_real(`data`, '[1]', 2) |
+--------------------------------+
| 12.00 |
+--------------------------------+
1 row in set (0.00 sec)
My stored procedure has IN parameter for page number (IN page INT)
And everything works fine for any value <= 2147483647.
And if value is > 2147483647 I get error 1264.
All this happens on 5.6.26 Community Server compiled for Linux (x86_64) and the same for 5.6.24 Community Server compiled for Win64 (x86_64)
And all of the above is fine and I understand the error.
However, on server 5.6.30-1+deb.sury.org~xenial+2 (Ubuntu) compiled for debian-linux-gnu (x86_64) this is not reproduced. Input value is just cut to 2147483647 no matter what value I pass there.
What setting is responsible for this "auto max value cap"? How can I synchronize settings on different environments without re-installation to have the same behavior?
Thank you!
Check 5.1.7 Server SQL Modes.
mysql> SELECT ##GLOBAL.SQL_MODE, ##SESSION.SQL_MODE;
+--------------------------------------------+--------------------------------------------+
| ##GLOBAL.SQL_MODE | ##SESSION.SQL_MODE |
+--------------------------------------------+--------------------------------------------+
| STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION | STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION |
+--------------------------------------------+--------------------------------------------+
1 row in set (0.00 sec)
mysql> DELIMITER //
mysql> DROP PROCEDURE IF EXISTS `sp_test`//
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> CREATE PROCEDURE `sp_test`(IN `page` INT)
-> BEGIN
-> SELECT `page`;
-> END//
Query OK, 0 rows affected (0.00 sec)
mysql> DELIMITER ;
mysql> CALL `sp_test`(2147483647);
+------------+
| `page` |
+------------+
| 2147483647 |
+------------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> CALL `sp_test`(2147483648);
ERROR 1264 (22003): Out of range value for column 'page' at row 1
mysql> SET ##SESSION.SQL_MODE = 'NO_ENGINE_SUBSTITUTION';
Query OK, 0 rows affected (0.00 sec)
mysql> select ##GLOBAL.SQL_MODE, ##SESSION.SQL_MODE;
+--------------------------------------------+------------------------+
| ##GLOBAL.SQL_MODE | ##SESSION.SQL_MODE |
+--------------------------------------------+------------------------+
| STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION | NO_ENGINE_SUBSTITUTION |
+--------------------------------------------+------------------------+
1 row in set (0.00 sec)
mysql> CALL `sp_test`(2147483648);
+------------+
| `page` |
+------------+
| 2147483647 |
+------------+
1 row in set (0.00 sec)
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> SHOW WARNINGS;
+---------+------+-----------------------------------------------+
| Level | Code | Message |
+---------+------+-----------------------------------------------+
| Warning | 1264 | Out of range value for column 'page' at row 1 |
+---------+------+-----------------------------------------------+
1 row in set (0.00 sec)
MariaDB [(none)]> SET #good = 10;
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> SHOW VARIABLES LIKE 'good';
Empty set (0.07 sec)
HOW show list all variables initialized by SET operator ?
For MySQL, use this:
select * from performance_schema.user_variables_by_thread;
MySQL Demo:
mysql> SET #good = 10;
Query OK, 0 rows affected (0.00 sec)
mysql> SET #bad = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from performance_schema.user_variables_by_thread;
+-----------+---------------+----------------+
| THREAD_ID | VARIABLE_NAME | VARIABLE_VALUE |
+-----------+---------------+----------------+
| 36922 | bad | 0 |
| 36922 | good | 10 |
+-----------+---------------+----------------+
2 rows in set (0.00 sec)
For MariaDB, it is not supported so far:
https://mariadb.com/kb/en/mariadb/information-schema-user_variables-table/
The USER_VARIABLES table will be introduced in MariaDB 10.2.0 as part of the user_variables plugin.
Recreating SQLs:
drop table t1;
set sql_mode = '';
create table t1 (c1 int, c2 int);
set sql_warnings = 0;
SHOW VARIABLES LIKE '%sql_warnings%';
insert into t1 values(1,'b');
set sql_warnings = 1;
SHOW VARIABLES LIKE '%sql_warnings%';
insert into t1 values(1,'b');
Output:
mysql> create table t1 (c1 int, c2 int);
Query OK, 0 rows affected (0.01 sec)
mysql> set sql_warnings = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW VARIABLES LIKE '%sql_warnings%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sql_warnings | OFF |
+---------------+-------+
1 row in set, 1 warning (0.01 sec)
mysql> insert into t1 values(1,'b');
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql>
mysql> set sql_warnings = 1;
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW VARIABLES LIKE '%sql_warnings%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sql_warnings | ON |
+---------------+-------+
1 row in set, 1 warning (0.00 sec)
mysql> insert into t1 values(1,'b');
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.7.8-rc |
+-----------+
1 row in set (0.00 sec)
From the output, no matter setting sql_warnings to 0 or 1, I am always getting the warnings in the INSERT statement.
Anyone knows why?
Update:
Result for "SHOW VARIABLES LIKE '%sql_warnings%';" is added above.
Filed a bug to MySQL and they verified it as a bug from version 5.0 to 5.7.
http://bugs.mysql.com/bug.php?id=80404
I am curious why this obvious behavior is not found before.