Quantcast
Channel: Shinguz's blog
Viewing all 292 articles
Browse latest View live

UNDO logs in InnoDB system tablespace ibdata1

$
0
0

We see sometimes at customers that they have very big InnoDB system tablespace files (ibdata1) although they have set innodb_file_per_table = 1.

So we want to know what else is stored in the InnoDB system tablespace file ibdata1 to see what we can do against this unexpected growth.

First let us check the size of the ibdata1 file:

# ll ibdata1 
-rw-rw---- 1 mysql mysql 109064486912 Dez  5 19:10 ibdata1

The InnoDB system tablespace is about 101.6 Gibyte in size. This is exactly 6'656'768 InnoDB blocks of 16 kibyte block size.

So next we want to analyse the InnoDB system tablespace ibdata1 file. For this we can use the tool innochecksum:

# innochecksum --page-type-summary ibdata1 
Error: Unable to lock file:: ibdata1
fcntl: Resource temporarily unavailable

But... the tool innochecksum throughs an error. It seems like it is not allowed to analyse the InnoDB system tablespace with a running database. So then let us stop the database first and try it again. Now we get a useful output:

# innochecksum --page-type-summary ibdata1 
File::ibdata1
================PAGE TYPE SUMMARY==============
#PAGE_COUNT     PAGE_TYPE
===============================================
  349391        Index page                        5.25%
 6076813        Undo log page                    91.29%
   18349        Inode page                        0.28%
  174659        Insert buffer free list page      2.62%
   36639        Freshly allocated page            0.55%
     405        Insert buffer bitmap              0.01%
      98        System page
       1        Transaction system page
       1        File Space Header
     404        Extent descriptor page            0.01%
       0        BLOB page
       8        Compressed BLOB page
       0        Other type of page
-------------------------------------------------------
 6656768        Pages total                     100.00%
===============================================
Additional information:
Undo page type: 3428 insert, 6073385 update, 0 other
Undo page state: 1 active, 67 cached, 249 to_free, 1581634 to_purge, 0 prepared, 4494862 other

So we can see that about 91% (about 92 Gibyte) of the InnoDB system tablespace ibdata1 blocks are used by InnoDB UNDO log pages. To avoid growing of ibdata1 you have to create a database instance with separate InnoDB UNDO tablespaces: Undo Tablespaces.

Taxonomy upgrade extras: 

Multi-Instance set-up with MySQL Enterprise Server 5.7 on RHEL 7 with SystemD

$
0
0

In our current project the customer wants to install and run multiple MySQL Enterprise Server 5.7 Instances on the same machine (yes, I know about virtualization (we run on kvm), containers, Docker, etc.). He wants to use Red Hat Enterprise Linux (RHEL) 7 which brings the additional challenge of SystemD. So mysqld_multi is NOT an option any more.

We studied the MySQL documentation about the topic: Configuring Multiple MySQL Instances Using systemd. But to be honest: It was not really clear to me how to do the job...

So we started to work out our own cook-book which I want to share here.

The requirements are as follows:

  • Only ONE version of MySQL Enterprise Server binaries at a time is available. If you want to have more complicated set-ups (multi version) consider our MyEnv.
  • Because Segregation of Duties is an issue for this customer from the financial industries we are not allowed to use the operating system root user or have sudo privileges.
  • We have to work with the operating system user mysql as non privileged user.

Preparation work for the operating system administrator

This is the only work which has to be done under a privileged account (root):

shell> sudo yum install libaio
shell> sudo groupadd mysql
shell> sudo useradd -r -g mysql -s /bin/bash mysql
shell> sudo cp mysqld@.service /etc/systemd/system/

Installation of MySQL Enterprise Server binaries as non privileged user

To perform this task we need the generic MySQL Binary Tar Balls which you can get from the Oracle Software Delivery Cloud:

shell> mkdir /home/mysql/product
shell> cd /home/mysql/product
shell> tar xf /download/mysql-<version>.tar.gz
shell> ln -s mysql-<version> mysql-5.7.x
shell> ln -s mysql-5.7.x mysql
shell> echo 'export PATH=$PATH:/home/mysql/product/mysql/bin'>> ~/.bashrc
shell> . ~/.bashrc

Creating, Starting and Stopping several MySQL Enterprise Server Instances

shell> export INSTANCE_NAME=TMYSQL01   # and TMYSQL02 and TMYSQL03
shell> mkdir -p /mysql/${INSTANCE_NAME}/etc /mysql/${INSTANCE_NAME}/log /mysql/${INSTANCE_NAME}/data /mysql/${INSTANCE_NAME}/binlog
shell> cat /mysql/${INSTANCE_NAME}/etc/my.cnf
#
# /mysql/${INSTANCE_NAME}/etc/my.cnf
#
[mysqld]
datadir   = /mysql/${INSTANCE_NAME}/data
pid_file  = /var/run/mysqld/mysqld_${INSTANCE_NAME}.pid
log_error = /mysql/${INSTANCE_NAME}/log/error_${INSTANCE_NAME}.log
port      = 3306   # and 3307 and 3308
socket    = /var/run/mysqld/mysqld_${INSTANCE_NAME}.sock
_EOF
shell> cd /home/mysql/product/mysql
shell> bin/mysqld --defaults-file=/mysql/${INSTANCE_NAME}/etc/my.cnf --initialize --user=mysql --basedir=/home/mysql/product/mysql
shell> bin/mysqld --defaults-file=/mysql/${INSTANCE_NAME}/etc/my.cnf --daemonize >/dev/null 2>&1 &
shell> mysqladmin --user=root --socket=/var/run/mysqld/mysqld_${INSTANCE_NAME}.sock --password shutdown

So far so good. We can do everything with the database without root privileges. One thing is missing: The MySQL Database Instances should be started automatically at system reboot. For this we need a SystemD unit file:

#
# /etc/systemd/system/mysqld@.service
#

[Unit]

Description=Multi-Instance MySQL Enterprise Server
After=network.target syslog.target


[Install]

WantedBy=multi-user.target
 

[Service]

User=mysql
Group=mysql
Type=forking
PIDFile=/var/run/mysqld/mysqld_%i.pid
TimeoutStartSec=3
TimeoutStopSec=3
# true is needed for the ExecStartPre
PermissionsStartOnly=true
ExecStartPre=/bin/mkdir -p /var/run/mysqld
ExecStartPre=/bin/chown mysql: /var/run/mysqld
ExecStart=/home/mysql/product/mysql/bin/mysqld --defaults-file=/mysql/%i/etc/my.cnf --daemonize
LimitNOFILE=8192
Restart=on-failure
RestartPreventExitStatus=1
PrivateTmp=false

This file must be copied as root to:

shell> cp mysqld@.service /etc/systemd/system/

Now you can check if SystemD behaves correctly as follows:

shell> sudo systemctl daemon-reload
shell> sudo systemctl enable mysqld@TMYSQL01   # also TMYSQL02 and TMYSQL03
shell> sudo systemctl start mysqld@TMYSQL01
shell> sudo systemctl status 'mysqld@TMYSQL*'
shell> sudo systemctl start mysqld@TMYSQL01

How to go even further

If you need a more convenient or a more flexible solution you can go with our MySQL Enterprise Environment MyEnv.

New Features in MySQL and MariaDB

$
0
0

As you probably know MySQL is an Open Source product licensed under the GPL v2. The GPL grants you the right to not just read and understand the code of the product but also to use, modify AND redistribute the code as long as you follow the GPL rules.

This redistribution has happened in the past various times. But in the western hemisphere only 3 of these branches/forks of MySQL are of relevance for the majority of the MySQL users: Galera Cluster for MySQL, MariaDB (Server and Galera Cluster) and Percona Server (and XtraDB Cluster).

Now it happened what has to happen in nature: The different branches/forks start to diverge (following the marketing rule: differentiate yourself from your competitors). The biggest an most important divergence happens now between MySQL and MariaDB.

Recently a customer of FromDual claimed that there is no more progress in the MySQL Server development whereas the MariaDB Server does significant progress. I was wondering a bit how this statement could have been made. So I try to summarize the New Features which have been added since the beginning of the separation starting with MySQL 5.1.

It is important to know, that some parts of MySQL code are directly or in modified form ported to MariaDB whereas some MariaDB features were implemented in MySQL as well. So missing features in MariaDB or improvements in MySQL can possibly make it sooner or later also into MariaDB and vice versa. Further both forks were profiting significantly from old MySQL 6.0 code which was never really announced broadly.

Further to consider: Sun Microsystems acquired MySQL in January 2008 (MySQL 5.1.23 was out then and MySQL 5.2, 5.4 and 6.0 were in the queue) and Sun was acquired by Oracle in January 2010 (MySQL 5.1.43, MySQL 5.5.1 were out, MySQL 5.2, 5.4 and 6.0 were abandoned and MySQL 5.6 was in the queue).

MySQL 5.1MariaDB 5.1 (link), 5.2 (link) and 5.3 (link)
  • Partitioning
  • Row-based replication
  • Plug-in API
  • Event scheduler.
  • Server log tables.
  • Upgrade program mysql_upgrade.
  • Improvements to INFORMATION_SCHEMA.
  • XML functions with Xpath support.

MariaDB 5.1

  • Storage Engines
    • Aria (Crash-safe MyISAM)
    • XtraDB plug-in (Branch of InnoDB)
    • PBXT (transactional Storage Engine)
    • Federated-X (replacement for Federated).
  • Performance
    • Faster CHECKSUM TABLE.
    • Character Set conversion improvement/elimination.
    • Speed-up of complex queries using Aria SE for temporary tables.
    • Optimizer: Table elimination.
  • Upgrade from MySQL 5.0 improved.
  • Better testing.
  • Microseconds precision in PROCESSLIST.

MariaDB 5.2

  • Storage Engines
    • OQGRAPH (Graph SE)
    • SphinxSE (Full-text search engine)
  • Performance
    • Segmented MyISAM key cache (instances)
    • Group Commit for Aria SE
  • Security
    • Pluggable Authentication
  • Virtual columns
  • Extended user statistics
  • Storage Engine specific CREATE TABLE
  • Enhancements to INFORMATION_SCHEMA.PLUGINS table

MariaDB 5.3

  • Performance
    • Subquery Optimization
      • Semi-join subquery optimizations
      • Non-semi-join optimizations
      • Subquery Cache
      • Subquery is not materialized any more in EXPLAIN
    • Optimization for derived tables and views
      • No early materialization of derived tables
      • Derived Table Merge optimization
      • Derived Table with Keys optimization
      • Fields of mergeable views and derived tables are involved in optimization
    • Disk access optimization
      • Index Condition Pushdown (ICP)
      • Multi-Range-Read optimization (MRR)
    • Join optimizations
      • Block-based Join Algorithms: Block Nested Loop (BNL) for outer joins, Block Hash Joins, Block Index Joins (Batched Key Access (BKA) Joins)
    • Index Merge improvements
  • Replication
    • Group Commit for Binary Log
    • Annotation of row-based replication events with the original SQL statement
    • Checksum for binlog events
    • Enhancements for START TRANSACTION WITH CONSISTENT SNAPSHOT
    • Performance improvement for row-based replication for tables with no primary key
  • Handler Socket Interface included.
  • HANDLER READ works with prepared statements
  • Dynamic Column support for Handler Interface
  • Microsecond support
  • CAST extended
  • Windows performance improvements
  • New status variables
  • Progress reports for some operations
  • Enhanced KILL command
MySQL 5.5 (link)MariaDB 5.5 (link)
  • InnoDB
    • InnoDB Version 5.5
    • Default storage engine switched to InnoDB.
    • InnoDB fast INDEX DROP/CREATE feature added.
    • Multi-core scalability. Focus on InnoDB, especially locking and memory management.
    • Optimizing InnoDB I/O subsystem to more effective use of available I/O capacity.
  • Performance
    • MySQL Thread Pool plug-in (Enterprise)
  • Security
    • MySQL Audit plug-in (Enterprise)
    • MySQL pluggable authentication (Enterprise) for LDAP, Kerberos, PAM and Windows login
  • Replication
    • Semi-synchronous replication.
  • Partitioning
    • 2 new partition types (RANGE COLUMNS, LIST COLUMNS).
    • TRUNCATE PARTITION.
  • Proxy Users
  • Diagnostic improvements to better access execution an performance information including PERFORMANCE_SCHEMA, expanded SHOW ENGINE INNODB STATUS output and new status variables.
  • Supplementary Unicode characters (utf16, utf32, utf8mb4).
  • CACHE INDEX and LOAD INDEX INTO CACHE for partitioned MyISAM tables.
  • Condition Handling: SIGNAL and RESIGNAL.
  • Introduction of Metadata locking to prevent DDL statements from compromising transactions serializability.
  • IPv6 Support
  • XML enhancement LOAD_XML_INFILE.
  • Build chain switched to CMake to ease build on other platforms including Windows.
  • Deprecation and remove of features.
  • Storage Engines
    • SphinxSE updated to 2.0.4
    • PBXT Storage Engine is deprecated.
  • XtraDB
    • MariaDB uses XtraDB 5.5 as compiled in SE and InnoDB 5.5 as plug-in.
    • Extended Keys support for XtraDB
  • Performance
    • Thread pool plug-in
    • Non-blocking client API Library
  • Replication
    • Updates on P_S tables are not logged to binary log.
    • replicate_* variables are dynamically.
    • Skip_replication option
  • LIMIT ROWS EXAMINED
  • New status variables for features.
  • New plug-in to log SQL level errors.
MySQL 5.6 (link)MariaDB 10.0 (link)
  • InnoDB
    • InnoDB Version 5.6
    • InnoDB full-text search.
    • InnoDB transportable tablespace support
    • Different InnoDB pages size implementation (4k, 8k, 16k)
    • Improvement of InnoDB adaptive flushing algorithm to make I/O more efficient.
    • NoSQL style Memcached API to access InnoDB data.
    • InnoDB optimizer persistent statistics.
    • InnoDB read-only transactions.
    • Separating InnoDB UNDO tablespace from system tablespace.
    • Maximum InnoDB transaction log size increased from 4G to 512G.
    • InnoDB read-only capability for read-only media (CD, DVD, etc.)
    • InnoDB table compression.
    • New InnoDB meta data table in INFORMATION_SCHEMA.
    • InnoDB internal performance enhancements.
    • Better InnoDB deadlock detection algorithm. Deadlock can be written to MySQL error log.
    • InnoDB buffer pool state saving and restoring capabilities.
    • InnoDB Monitor dynamially disable/enable.
    • Online and inplace DDL operations for normal and partitioned InnoDB Tables to reduce application downtime.
  • Optimizer
    • ORDER BY non-index-column for simple queries and subqueries
    • Disk-Sweep Multi-Range Read (MRR) optimization for secondary index/table access to reduce I/O
    • Index Condition Pushdown (ICP) optimization by pushing down the WHERE filter to the storage engine.
    • EXPLAIN also works for DML statemetns.
    • Optimizing of subqueries in derived tables (FROM (...)) by postponing or indexing deived tables.
    • Implementation of semi-join and materialization strategies to optimize subquery execution.
    • Batched Key Access (BKA) join algorithm to improve join performance during table scanning.
    • Optimizer trace capabilities.
  • Performance Schema (P_S)
    • Instrumentation for Statements and stages
    • Configuration of consumers at server startup
    • Summary tables for table and index I/O and for table locks
    • Event filtering by table
    • Various new instrumentation.
  • Security
    • Encrypted authentication credentials
    • Stronger encryption for passwords (SHA-256 authentication plugin)
    • MySQL User password expiration.
    • Password validation plugin to check password strength
    • mysql_install_db can create secure root password by default
    • cleartext password is not written to any log file any more.
    • MySQL Firewall (Enterprise)
  • Replication
    • Transaction based replication using global transaction identifiers (GTID)
    • Row Image Control to reduce binary log volume.
    • Crash-safe replication with checksumming and verfiying.
    • IO and SQL thread information can be stored in an transactional table inside the DB.
    • MySQL binlog streaming with mysqlbinlog possible.
    • Delayed replication
    • Parallel replication on schema level.
  • Partitioning
    • Number of partitions including subpartitions increased to 8192.
    • Exchange partition with a normal table.
    • Explicit selection of specific partiton is possible.
    • Partition lock prunining for DML and DDL statements.
  • Condition handling: GET DIAGNOSTICS and SET DIAGNOSTICS
  • Server defaults changes.
  • Data types TIME, DATETIME and TIMESTAMP with microseconds
  • Host cache exposure and connection errors status infromation for finding connection problems.
  • Improvement in GIS functions.
  • Deprecation and remove of features.
  • Storage Engine
    • Cassandra Storage Engine
    • Conncect Storage Engine
    • Squence Storage Engine
    • Better table discovery (Federated-X)
    • Spider Storage Engine
    • TokuDB Storage Engine
    • Mroonga fulltext search Storage Engine
  • XtraDB
    • XtraDB Version 5.6
    • Async commit checkpoint in XtraDB and InnoDB
    • Support for atomic writes on FusionIO DirectFS
  • Replication
    • Parallel Replication
    • Global Transaction ID (GTID)
    • Multi Source Replication
  • Performance
    • Subquery Optimization (EXISTS to IN)
    • Faster UNIQUE KEY generation
    • Shutdown performance improvment for MyISAM/Aria table (adjustable hash size)
  • Security
    • Roles
    • MariaDB Audit Plugin
  • Optimizer
    • EXPLAIN for DML Statements
    • Engine independent table statistics
    • Histogram based statistics
    • QUERY_RESPONSE_TIME plugin
    • SHOW EXPLAIN for running connections
    • EXPLAIN in the Slow Query Log
  • Per thread memory usage statistics
  • SHOW PLUGINS SONAME
  • SHUTDOWN command
  • Killing a query by query id not thread id.
  • Return result set of delete rows with DELETE ... RETURNING
  • ALTER TABLE IF (NOT) EXISTS
  • CREATE OR REPLACE TABLE
  • Dynamic columns referenced by name
  • Multiple use locks (GET_LOCK) in one connection
  • Better error messages
  • New regular expressions (PCRE) REGEXP_REPLACE, REGEXP_INSTR, REGEXP_SUBSTR
  • Metadata lock information in INFORMATION_SCHEMA
  • Priority queue optimzation visibility
  • FLUSH TABLE ... FOR EXPORT flushes changes to disk for binary copy
  • CURRENT_TIMESTAMP as DEFAULT for DATETIME
  • Various features backported from MySQL 5.6
MySQL 5.7 (link)MariaDB 10.1 (link)
  • InnoDB
    • InnoDB Version 5.7
    • VAR CHAR size increase can be in-place in some cases.
    • DDL performance improvements for temporary InnoDB tables (CREATE DROP TRUNCATE, ALTER)
    • Active InnoDB temporary table metadata are exposed in table INNODB_TEMP_TABLE_INFO.
    • InnoDB support spatial data type (GIS, DATA_GEOMETRY)
    • Separate tablespace for temporary InnoDB tables.
    • Support for InnoDB Full-text parser plugins was added.
    • Multiple page cleaner threads were added.
    • Regular an paritioned InnoDB tables can be rebuilt using online inplace DDL commands (OPTIMZE, ALTER TABLE FORCE)
    • Automatic detection, support and optimization for Fusion-io NVM file system to support atomic writes.
    • Better support for Transportable Tablespaces to ease backup process.
    • InnoDB Buffer Pool size can be configured dynamically.
    • Multi-threaded page cleaner support for shutdown and recovery phase.
    • InnoDB spatial index support for online in place operation (ADD SPATIAL INDEX)
    • InnoDB sorted index builds to improve bulk loads.
    • Identification of modified tablespaces to increase crash recovery performance.
    • InnoDB UNDO log truncation.
    • InnoDB native partion support.
    • InnoDB general tablespace support for databases with a huge amount of tables.
    • InnoDB data at rest encryption for file-per-table tablespaces.
  • Performance
    • EXPLAIN for running connections (FOR CONNECTIONS)
    • Finer Control of optimizer hints.
  • Security
    • Old password support has been removed.
    • Autmomatic password expiry policies.
    • Lock and unlock of accounts.
    • SSL and RSA certificate and key file generation.
    • SSL enabled automatically if available.
    • MySQL will be initialized secure by default (= hardened)
    • STRICT_TRANS_TABLES sql_mode is now enabled by default.
    • ONLY_FULL_GROUP_BY sql_mode made more sophisticated to only prohibit non deterministic query.
  • Replication
    • Master dump thread was refactored to improve throughput.
    • Replication Master change without STOP SLAVE.
    • Multi-source replication introduced.
  • Partitioning
    • HANDLER statment works now on partitioned tables.
    • Index Condition Pushdown (ICP) works for partitioned InnoDB and MyISAM tables.
    • ALTER TABLE EXCHANGE PARTITION WITHOU VALIDATION is possible to improve performance of exchnage.
  • Native JSON support
    • Data type JSON.
    • JSON functions: JSON_ARRAY, JSON_MERGE, JSON_OBJECT, JSON_CONTAINS, JSON_CONTAINS_PATH, JSON_EXTRACT, JSON_KEYS, JSON_SEARCH, JSON_APPEND, JSON_ARRAY_APPEND, JSON_ARRAY_INSERT, JSON_INSERT, JSON_QUOTE, JSON_REMOVE, JSON_REPLACE, JSON_SET, JSON_UNQUOTE, JSON_DEPTH, JSON_LENGTH, JSON_TYPE, JSON_VALID
  • System and status variables moved from INFORMATION_SCHEMA to PERFORMANCE_SCHEMA.
  • Sys Schema created by default.
  • Condition handling: GET STACKED DIAGNOSTICS
  • Multiple triggers per event are possible now.
  • Native logging to syslog possible.
  • Generated Column support.
  • Database rewriting in mysqlbinlog.
  • Control+C in mysql client does not exit any more but interrupts query only.
  • New China National Standard GB18030 character set.
  • RENAME INDEX is online inplace without a table copy.
  • Chinese, Japanese and Korean (CJK) full-text parser implemented (ngram MeCab full-test parser plugins).
  • Deprecation and remove of features.
  • XtraDB
    • Allow up to 64K pages in InnoDB (old limit was 16K).
    • Defragmenting InnoDB Tablespaces improved which uses OPTIMIZE TABLE to defragment InnoDB tablespaces.
    • XtraDB page compression
  • Performance
    • Page compression for FusionIO
    • Do not create .frm files for temporary tables.
    • UNION ALL works without usage of a temporary table.
    • Scalability fixes for Power8.
    • Performance improvementes on simple queries.
    • Performance Schema tables no longer use .frm files.
    • xid cache scalability was significantly improved.
  • Replication
    • Optimistic mode of in-order parallel replication
    • domain_id based replication filters
    • Enhanced semisync replication: Wait for at least one slave to acknowledge transaction before committing.
    • Triggers can now be run on the slave for row-based events.
    • Dump Thread Enhancements: Makes multiple slave setups faster by allowing concurrent reading of binary log.
    • Throughput improvements in parallel replication.
    • RESET_MASTER is extended with TO.
  • Optimizer
    • ANALYZE statement provides output for how many rows were actually read, etc.
    • EXPLAIN FORMAT=JSON
    • ORDER BY optimization is improved.
    • MAX_STATEMENT_TIME can be used to automatically abort long running queries.
  • Security
    • Password validation plug-in API.
    • Simple password check password validation plugin.
    • Cracklib_password_check password validation plugin.
    • Table, Tablespace and Log at-rest encryption (TDE)
    • SET DEFAULT ROLE
    • New columns for the INFORMATION_SCHEMA.APPLICABLE_ROLES table.
  • Galera Cluster plug-in becomes standard in MariaDB.
  • Wsrep information in INFORMATION_SCHEMA: WSREP_MEMBERSHIP and WSREP_STATUS
  • Consistent support for IF EXISTS and IF NOT EXISTS and OR REPLACE for: CREATE DATABASE, CREATE FUNCTION UDF, CREATE ROLE, CREATE SERVER, CREATE USER, CREATE VIEW, DROP ROLE, DROP USER, CREATE EVENT, DROP EVENT, CREATE INDEX, DROP INDEX, CREATE TRIGGER, DROP TRIGGER
  • Information Schema plugins can now support SHOW and FLUSH statements.
  • GET_LOCK() now supports microseconds in the timeout.
  • The number of rows affected by a slow UPDATE or DELETE is now recorded in the slow query log.
  • Anonymous Compount Statents blocks are supported.
  • SQL standards-compliant behavior when dealing with Primary Keys with Nullable Columns.
  • Automatic discovery of PERFORMANCE_SCHEMA tables.
  • INFORMATION_SCHEMA.SYSTEM_VARIABLES, enforce_storage_engine, default-tmp-storage-engine, mysql56-temporal-format, Slave_skipped_errors, silent-startup
  • New status variables to show the number of grants on different object.
  • Set variables per statement: SET STATEMENT
  • Support for Spatial Reference systems for the GIS data.
  • More functions from the OGC standard added: ST_Boundary, ST_ConvexHull, ST_IsRing, ST_PointOnSurface, ST_Relate
  • GIS INFORMATION_SCHEMA tables: GEOMETRY_COLUMNS, SPATIAL_REF_SYS
MySQL 8.0 (link)MariaDB 10.2 (link)
  • InnoDB
    • InnoDB Version 8.0
    • AUTO_INCREMENT values are persisted accross server restarts.
    • Index corruption and in-memory corruption detection written persistently to the transaction log.
    • InnoDB Memcached plug-in supports multiple get operations.
    • Deadlock detection can be disabled and leads to a lock timeout to increase performance.
    • Index pages cached in buffer pool are listed in INNODB_CACHED_INDEXES.
    • All InnoDB temporary tables are created in InnoDB shared temporary tablespace.
  • JSON
    • Inline path operator ->> added.
    • Column paht operator -> improved.
    • JSON aggregation functions JSON_ARRAYAGG() and JSON_OBJECTAGG() added.
  • Security
    • Account management supports roles.
    • Aromicity in User Management DDLs.
  • Transactional data dictionary (DD).
  • Common Table Expressions (CTE, recursive SQL, Series creation)
  • Descending Indexes
  • Scaling and Performance of INFORMATION_SCHEMA (1 Mio table problem)
  • Deprecation and remove of features.

MySQL 8.0 is currently in a very early stage (DMR) so this list will increase over time!

  • XtraDB
    • XtraDB Version 5.6
  • Security
    • SHOW CREATE USER
    • CREATE USER and ALTER USER extended for limiting resources and TLS/SSL support.
  • Performance
    • Connection creation speed-up by separate thread.
  • Optimizer
    • EXPLAIN FORMAT=JSON improved.
  • Partition
    • Catchall partion for LIST partions.
  • Introduction of Window functions: CUME_DIST, DENSE_RANK, NTILE, PERCENT_RANK, RANK, ROW_NUMBER
  • SHOW CREATE USER statement and limiting user resource usage introduced
  • Common Table Expression (CTE) WITH clause for recursive queries.
  • CHECK CONSTRAINT support.
  • Support for DEFAULT with expression.
  • BLOB and TEXT can now have default values.
  • Virtual computed columns restrictions lifted.
  • Supported decimals in DECIMAL increased from 30 to 38.
  • Temporary tables can be referred to several times in the same query.
  • Multiple triggers for the same event.
  • InnoDB/XtraDB 5.7.14 was merged.
  • ANALYZE TABLE implemented lock free.
  • CONNECT engine supports JDBC table type.
  • NO PAD collation support.
  • Table cache can auto-partition introduced.
  • New Window functions: LEAD, LAG, NTH_VALUE, FIRST_VALUE, LAST_VALUE
  • Slave binary log read throttling, delayed replication, and binary log compression implemented.
  • JSON functions added
  • Oracle style EXECUTE IMMEDIATE.
  • PREPARE STATEMENT understand most expressions.
  • TRIGGERS enhanced by FOLLOWS/PRECEDES clauses.
  • I_S.USER_VARIABLES introduced as plug-in.
  • New status information: Com_alter_user, Com_multi, Com_show_create_user.
  • New variables: innodb_tmpdir, read_binlog_speed_limit.
  • DML flashback introduced on instance, database and table level.
  • GeoJSON functions added.
  • To come soon
    • MariaDB Column store (ex. InfiniDB)
    • MyRocks?

MariaDB 10.2 is currently in a early stage (beta release) so this list will increase over time...

MySQL 9.0MariaDB 10.3 (link) and 10.4

No details are known yet. MySQL developer meetingt took place in November 2016.

  • Suggested features
    • Hidden columns
    • Long unique constraints
    • SQL based CREATE AGGREGATE FUNCTION
    • New data types: IPv6, UUID, pluggable data-type API
    • Better support for CJK (Chinese, Japanese, and Korean) languages. Include the ngram full-text parser and MeCab full-text parser .
    • Improvement of Spider SE.
    • Support for SEQUENCES
    • Additional PL/SQL parser
    • Support for INTERSECT
    • Support for EXCEPT

MariaDB 10.3 is currently in a very early stage so this list will increase over time!


Please let me know if I got something wrong or forgot any significant feature for theses 2 MySQL branches.

Taxonomy upgrade extras: 

MySQL and MariaDB variables inflation

$
0
0

MySQL is well known and widely spread because of its philosophy of Keep it Simple (KISS).

We recently had the discussion that with newer releases also MySQL and MariaDB relational databases becomes more and more complicated.

One indication for this trend is the number of MySQL server system variables and status variables.

In the following tables and graphs we compare the different releases since MySQL version 4.0:

mysql> SHOW GLOBAL VARIABLES;
mysql> SHOW GLOBAL VARIABLES LIKE 'innodb%';
mysql> SHOW GLOBAL STATUS;
mysql> SHOW GLOBAL STATUS LIKE 'innodb%';

VersionSystemIB Sys.StatusIB Stat.
MySQL 4.0.3014322*133**0
MySQL 4.1.2518926*164**0
MySQL 5.0.962393625242
MySQL 5.1.732773629142
MySQL 5.5.513176031247
MySQL 5.6.3143812034151
MySQL 5.7.1549113135351
MySQL 8.0.048812436351

* Use SHOW STATUS instead.
** Use SHOW ENGINE INNODB STATUS\G instead.

inflation_mysql.png

VersionSystemIB Sys.StatusIB Stat.
MariaDB 5.1.443547230144
MariaDB 5.2.103978632446
MariaDB 5.5.4141910341399
MariaDB 10.0.2153714745595
MariaDB 10.1.18***589178517127
MariaDB 10.2.2****58616448196

*** XtraDB 5.6
****InnoDB 5.7.14???

inflation_mariadb.png

Taxonomy upgrade extras: 

MySQL replication with filtering is dangerous

$
0
0

From time to time we see in customer engagements that MySQL Master/Slave replication is set-up doing schema or table level replication filtering. This can be done either on Master or on Slave. If filtering is done on the Master (by the binlog_{do|ignore}_db settings), the binary log becomes incomplete and cannot be used for a proper Point-in-Time-Recovery. Therefore FromDual recommends AGAINST this approach.

The replication filtering rules vary depending on the binary log format (ROW and STATEMENT) See also: How Servers Evaluate Replication Filtering Rules.

For reasons of data consistency between Master and Slave FromDual recommends to use only the binary log format ROW. This is also stated in the MySQL documentation: All changes can be replicated. This is the safest form of replication. Especially dangerous is binary log filtering with binary log format MIXED. This binary log format FromDual strongly discourages users to use.

The binary log format ROW affects only DML statements (UPDATE, INSERT, DELETE, etc.) but NOT DDL statements (CREATE, ALTER, DROP, etc.) and NOT DCL statements (CREATE, GRANT, REVOKE, DROP, etc.). So how are those statements replicated? They are replicated in STATEMENT binary log format even though binlog_format is set to ROW. This has the consequences that the binary log filtering rules of STATEMENT based replication and not the ones of ROW based replication apply when running one of those DDL or DCL statements.

This can easily cause problems. If you are lucky, they will cause the replication to break sooner or later, which you can detect and fix - but they may also cause inconsistencies between Master and Slave which may remain undetected for a long time.

Let us show what happens in 2 similar scenarios:

Scenario A: Filtering on mysql schema

On Slave we set the binary log filter as follows:

replicate_ignore_db = mysql

and verify it:

mysql> SHOW SLAVE STATUS\G
...
          Replicate_Ignore_DB: mysql
...

The intention of this filter setting is to not replicate user creations or modifications from Master to the Slave.

We verify on the Master, that binlog_format is set to the wanted value:

mysql> SHOW GLOBAL VARIABLES LIKE 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW   |
+---------------+-------+

Now we do the following on the Master:

mysql> use mysql
mysql> CREATE USER 'inmysql'@'%';
mysql> use test
mysql> CREATE USER 'intest'@'%';

and verify the result on the Master:

mysql> SELECT user, host FROM mysql.user;
+-------------+-----------+
| user        | host      |
+-------------+-----------+
| inmysql     | %         |
| intest      | %         |
| mysql.sys   | localhost |
| root        | localhost |
+-------------+-----------+

and on the Slave:

mysql> SELECT user, host FROM mysql.user;
+-------------+-----------+
| user        | host      |
+-------------+-----------+
| intest      | %         |
| mysql.sys   | localhost |
| root        | localhost |
+-------------+-----------+

We see, that the user intest was replicated and the user inmysql was not. And we have clearly an unwanted data inconsistency between Master and Slave.

If we want to drop the inmysql user some time later on the Master:

mysql> use myapp;
mysql> DROP USER 'inmysql'@'%';

we get the following error message on the Slave and are wondering, why this user or the query appears on the Slave:

mysql> SHOW SLAVE STATUS\G
...
               Last_SQL_Errno: 1396
               Last_SQL_Error: Error 'Operation DROP USER failed for 'inmysql'@'%'' on query. Default database: 'test'. Query: 'DROP USER 'inmysql'@'%''
...

A similar problem happens when we connect to NO database on the Master as follows and change the users password:

shell> mysql -uroot
mysql> SELECT DATABASE();
+------------+
| database() |
+------------+
| NULL       |
+------------+
mysql> ALTER USER 'innone'@'%' IDENTIFIED BY 'secret';

This works perfectly on the Master. But what happens on the Slave:

mysql> SHOW SLAVE STATUS\G
...
               Last_SQL_Errno: 1396
               Last_SQL_Error: Error 'Operation ALTER USER failed for 'innone'@'%'' on query. Default database: ''. Query: 'ALTER USER 'innone'@'%' IDENTIFIED WITH 'mysql_native_password' AS '*14E65567ABDB5135D0CFD9A70B3032C179A49EE7''
...

The Slave wants to tell us in a complicated way, that the user innone does not exist on the Slave...

Scenario B: Filtering on tmp or similar schema

An other scenario we have seen recently is that the customer is filtering out tables with temporary data located in the tmp schema. Similar scenarios are cache, session or log tables. He did it as follows on the Master:

mysql> use tmp;
mysql> TRUNCATE TABLE tmp.test;

As he has learned in FromDual trainings he emptied the table with the TRUNCATE TABLE command instead of a DELETE FROM tmp.test command which is much less efficient than the TRUNCATE TABLE command. What he did not consider is, that the TRUNCATE TABLE command is a DDL command and not a DML command and thus the STATEMENT based replication filtering rules apply. His filtering rules on the Slave were as follows:

mysql> SHOW SLAVE STATUS\G
...
          Replicate_Ignore_DB: tmp
...

When we do the check on the Master we get an empty set as expected:

mysql> SELECT * FROM tmp.test;
Empty set (0.00 sec)

When we add new data on the Master:

mysql> INSERT INTO tmp.test VALUES (NULL, 'new data', CURRENT_TIMESTAMP());
mysql> SELECT * FROM tmp.test;
+----+-----------+---------------------+
| id | data      | ts                  |
+----+-----------+---------------------+
|  1 | new data  | 2017-01-11 18:00:11 |
+----+-----------+---------------------+

we get a different result set on the Slave:

mysql> SELECT * FROM tmp.test;
+----+-----------+---------------------+
| id | data      | ts                  |
+----+-----------+---------------------+
|  1 | old data  | 2017-01-11 17:58:55 |
+----+-----------+---------------------+

and in addition the replication stops working with the following error:

mysql> SHOW SLAVE STATUS\G
...
                   Last_Errno: 1062
                   Last_Error: Could not execute Write_rows event on table tmp.test; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log laptop4_qa57master_binlog.000042, end_log_pos 1572
...

See also our earlier bug report of a similar topic: Option "replicate_do_db" does not cause "create table" to replicate ('row' log)

Conclusion

Binary log filtering is extremely dangerous when you care about data consistency and thus FromDual recommends to avoid binary log filtering by all means. If you really have to do binary log filtering you should exactly know what you are doing, carefully test your set-up, check your application and your maintenance jobs and also review your future code changes regularly. Otherwise you risk data inconsistencies in your MySQL Master/Slave replication.

Is your MySQL software Cluster ready?

$
0
0

When we do Galera Cluster consulting we always discuss with the customer if his software is Galera Cluster ready. This basically means: Can the software cope with the Galera Cluster specifics?

If it is a software product developed outside of the company we recommend to ask the software vendor if the software supports Galera Cluster or not.

We typically see 3 different answers:

  • We do not know. Then they are at least honest.
  • Yes we do support Galera Cluster. Then they hopefully know what they are talking about but you cannot be sure and should test carefully.
  • No we do not. Then they most probably know what they are talking about.

If the software is developed in-house it becomes a bit more tricky because the responsibility for this statement has to be taken by you or some of your colleagues.

Thus it is good to know what are the characteristics and the limitations of a Cluster like Galera Cluster for MySQL.

Most of the Galera restrictions an limitation you can find here.

DDL statements cause TOI operations

DDL and DCL statements (like CREATE, ALTER, TRUNCATE, OPTIMIZE, DROP, GRANT, REVOKE, etc.) are executed by default in Total Order Isolation (TOI) by the Online Schema Upgrade (OSU) method. To achieve this schema upgrade consistently Galera does a global Cluster lock.

It is obvious that those DDL operations should be short and not very frequent to not always block your Galera Cluster. So changing your table structure must be planned and done carefully to not impact your daily business operation.

But there are also some not so obvious DDL statements causing TOI operations (and Cluster locks).

  • TRUNCATE TABLE ... This operation is NOT a DML statement (like DELETE) but a DDL statement and thus does a TOI operation with a Cluster lock.
  • CREATE TABLE IF NOT EXISTS ... This operation is clearly a DDL statement but one might think that it does NOT a TOI operation if the table already exists. This is wrong. This statement causes always a TOI operation if the table is there or not does not matter. If you run this statement very frequent this potentially causes troubles to your Galera Cluster.
  • CREATE TABLE younameit_tmp ... The intention is clear: The developer wants to create a temporary table. But this is NOT a temporary table but just a normal table called _tmp. So it causes as TOI operation as well. What you should do in this case is to create a real temporary table like this: CREATE TEMPORARY TABLE yournameit_tmp ... This DDL statement is only executed locally and will not cause a TOI operation.

How to check?

You can check the impact of this problem with the following sequence of statements:

mysql> SHOW GLOBAL STATUS LIKE 'Com_create_table%';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| Com_create_table | 4     |
+------------------+-------+

mysql> CREATE TABLE t1_tmp (id INT);

mysql> SHOW GLOBAL STATUS LIKE 'Com_create_table%';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| Com_create_table | 5     | --> Also changes on the Slave nodes!
+------------------+-------+

mysql> CREATE TEMPORARY TABLE t2_tmp (id INT);

mysql> SHOW GLOBAL STATUS LIKE 'Com_create_table%';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| Com_create_table | 6     | --> Does NOT change on the Slave nodes!
+------------------+-------+

mysql> CREATE TABLE IF NOT EXISTS t1_tmp (id INT);
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| Com_create_table | 7     | --> Also changes on the Slave nodes!
+------------------+-------+

Find out in advance

If you want to find out before migrating to Galera Cluster if you are hit by this problem or not you can either run:

mysql> SHOW GLOBAL STATUS
WHERE variable_name LIKE 'Com_create%'
   OR variable_name LIKE 'Com_alter%'
   OR variable_name LIKE 'Com_drop%'
   OR variable_name LIKE 'Com_truncate%'
   OR variable_name LIKE 'Com_grant%'
   OR variable_name LIKE 'Com_revoke%'
   OR variable_name LIKE 'Com_optimize%'
   OR variable_name LIKE 'Com_rename%'
   OR variable_name LIKE 'Uptime'
;
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| Com_create_db        | 2     |
| Com_create_table     | 6     |
| Com_optimize         | 1     |
| Uptime               | 6060  |
+----------------------+-------+

Or if you want to know exactly who was running the query from the PERFORMANCE_SCHEMA:

SELECT user, host, SUBSTR(event_name, 15) AS event_name, count_star
  FROM performance_schema.events_statements_summary_by_account_by_event_name
 WHERE count_star > 0 AND
     ( event_name LIKE 'statement/sql/create%'
    OR event_name LIKE 'statement/sql/alter%'
    OR event_name LIKE 'statement/sql/drop%'
    OR event_name LIKE 'statement/sql/rename%'
    OR event_name LIKE 'statement/sql/grant%'
    OR event_name LIKE 'statement/sql/revoke%'
    OR event_name LIKE 'statement/sql/optimize%'
    OR event_name LIKE 'statement/sql/truncate%'
    OR event_name LIKE 'statement/sql/repair%'
    OR event_name LIKE 'statement/sql/check%'
     )
;
+------+-----------+--------------+------------+
| user | host      | event_name   | count_star |
+------+-----------+--------------+------------+
| root | localhost | create_table |          4 |
| root | localhost | create_db    |          2 |
| root | localhost | optimize     |          1 |
+------+-----------+--------------+------------+

If you need help to make your application Galera Cluster ready we will be glad to assist you.

MySQL and MariaDB authentication against pam_unix

$
0
0

The PAM authentication plug-in is an extension included in MySQL Enterprise Edition (since 5.5) and in MariaDB (since 5.2).

MySQL authentication against pam_unix


Check if plug-in is available:

# ll lib/plugin/auth*so
-rwxr-xr-x 1 mysql mysql 42937 Sep 18  2015 lib/plugin/authentication_pam.so
-rwxr-xr-x 1 mysql mysql 25643 Sep 18  2015 lib/plugin/auth.so
-rwxr-xr-x 1 mysql mysql 12388 Sep 18  2015 lib/plugin/auth_socket.so
-rwxr-xr-x 1 mysql mysql 25112 Sep 18  2015 lib/plugin/auth_test_plugin.so

Install PAM plug-in:

mysql> INSTALL PLUGIN authentication_pam SONAME 'authentication_pam.so';

Check plug-in information:

mysql> SELECT * FROM information_schema.plugins WHERE plugin_name = 'authentication_pam'\G
*************************** 1. row ***************************
           PLUGIN_NAME: authentication_pam
        PLUGIN_VERSION: 1.1
         PLUGIN_STATUS: ACTIVE
           PLUGIN_TYPE: AUTHENTICATION
   PLUGIN_TYPE_VERSION: 1.1
        PLUGIN_LIBRARY: authentication_pam.so
PLUGIN_LIBRARY_VERSION: 1.7
         PLUGIN_AUTHOR: Georgi Kodinov
    PLUGIN_DESCRIPTION: PAM authentication plugin
        PLUGIN_LICENSE: PROPRIETARY
           LOAD_OPTION: ON

It seems like this set-up is persisted and survives a database restart because of the mysql schema table:

mysql> SELECT * FROM mysql.plugin;
+--------------------+-----------------------+
| name               | dl                    |
+--------------------+-----------------------+
| authentication_pam | authentication_pam.so |
+--------------------+-----------------------+

Configuring PAM on Ubuntu/Debian:

#%PAM-1.0
#
# /etc/pam.d/mysql
#
@include common-auth
@include common-account
@include common-session-noninteractive

Create the database user matching to the O/S user:

mysql> CREATE USER 'oli'@'localhost'
IDENTIFIED WITH authentication_pam AS 'mysql'
;
mysql> GRANT ALL PRIVILEGES ON test.* TO 'oli'@'localhost';

Verifying user in the database:

mysql> SELECT user, host, authentication_string FROM `mysql`.`user` WHERE user = 'oli';
+-----------+-----------+-------------------------------------------+
| user      | host      | authentication_string                     |
+-----------+-----------+-------------------------------------------+
| oli       | localhost | mysql                                     |
+-----------+-----------+-------------------------------------------+

mysql> SHOW CREATE USER 'oli'@'localhost';
+-----------------------------------------------------------------------------------------------------------------------------------+
| CREATE USER for oli@localhost                                                                                                     |
+-----------------------------------------------------------------------------------------------------------------------------------+
| CREATE USER 'oli'@'localhost' IDENTIFIED WITH 'authentication_pam' AS 'mysql' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK |
+-----------------------------------------------------------------------------------------------------------------------------------+

Connection tests:

# mysql --user=oli --host=localhost
ERROR 2059 (HY000): Authentication plugin 'mysql_clear_password' cannot be loaded: plugin not enabled

# mysql --user=oli --host=localhost --enable-cleartext-plugin --password=wrong
ERROR 1045 (28000): Access denied for user 'oli'@'localhost' (using password: YES)

# tail /var/log/auth.log
Feb 13 15:15:14 chef unix_chkpwd[31600]: check pass; user unknown
Feb 13 15:15:14 chef unix_chkpwd[31600]: password check failed for user (oli)

# mysql --user=oli --host=localhost --enable-cleartext-plugin --password=rigth
ERROR 1045 (28000): Access denied for user 'oli'@'localhost' (using password: YES)

# tail /var/log/auth.log
Feb 13 15:15:40 chef unix_chkpwd[31968]: check pass; user unknown
Feb 13 15:15:40 chef unix_chkpwd[31968]: password check failed for user (oli)

Some research led to the following result: The non privileged mysql user is not allowed to access the file /etc/shadow thus it should be added to the group shadow to make it work:

# ll /sbin/unix_chkpwd
-rwxr-sr-x 1 root shadow 35536 Mar 16  2016 /sbin/unix_chkpwd

# usermod -a -G shadow mysql


Connection tests:

# mysql --user=oli --host=localhost --enable-cleartext-plugin --password=rigth

mysql> SELECT USER(), CURRENT_USER(), @@proxy_user;
+---------------+----------------+--------------+
| USER()        | CURRENT_USER() | @@proxy_user |
+---------------+----------------+--------------+
| oli@localhost | oli@localhost  | NULL         |
+---------------+----------------+--------------+

MariaDB authentication against pam_unix


Check if plug-in is available:

# ll lib/plugin/auth*so
-rwxr-xr-x 1 mysql mysql 12462 Nov  4 14:37 lib/plugin/auth_0x0100.so
-rwxr-xr-x 1 mysql mysql 33039 Nov  4 14:37 lib/plugin/auth_gssapi_client.so
-rwxr-xr-x 1 mysql mysql 80814 Nov  4 14:37 lib/plugin/auth_gssapi.so
-rwxr-xr-x 1 mysql mysql 19015 Nov  4 14:37 lib/plugin/auth_pam.so
-rwxr-xr-x 1 mysql mysql 13028 Nov  4 14:37 lib/plugin/auth_socket.so
-rwxr-xr-x 1 mysql mysql 23521 Nov  4 14:37 lib/plugin/auth_test_plugin.so

Install PAM plug-in:

mysql> INSTALL SONAME 'auth_pam';

Check plug-in information:

mysql> SELECT * FROM information_schema.plugins WHERE plugin_name = 'pam'\G
*************************** 1. row ***************************
           PLUGIN_NAME: pam
        PLUGIN_VERSION: 1.0
         PLUGIN_STATUS: ACTIVE
           PLUGIN_TYPE: AUTHENTICATION
   PLUGIN_TYPE_VERSION: 2.0
        PLUGIN_LIBRARY: auth_pam.so
PLUGIN_LIBRARY_VERSION: 1.11
         PLUGIN_AUTHOR: Sergei Golubchik
    PLUGIN_DESCRIPTION: PAM based authentication
        PLUGIN_LICENSE: GPL
           LOAD_OPTION: ON
       PLUGIN_MATURITY: Stable
   PLUGIN_AUTH_VERSION: 1.0

Configuring PAM on Ubuntu/Debian:

#%PAM-1.0
#
# /etc/pam.d/mysql
#
@include common-auth
@include common-account
@include common-session-noninteractive

Create the database user matching to the O/S user:

mysql> CREATE USER 'oli'@'localhost'
IDENTIFIED VIA pam USING 'mariadb'
;
mysql> GRANT ALL PRIVILEGES ON test.* TO 'oli'@'localhost';

Verifying user in the database:

mysql> SELECT user, host, authentication_string FROM `mysql`.`user` WHERE user = 'oli';
+------+-----------+-----------------------+
| user | host      | authentication_string |
+------+-----------+-----------------------+
| oli  | localhost | mariadb               |
+------+-----------+-----------------------+

Connection tests:

# mysql --user=oli --host=localhost --password=wrong
ERROR 2059 (HY000): Authentication plugin 'dialog' cannot be loaded: /usr/local/mysql/lib/plugin/dialog.so: cannot open shared object file: No such file or directory

# tail /var/log/auth.log
Feb 13 17:11:16 chef mysqld: pam_unix(mariadb:auth): unexpected response from failed conversation function
Feb 13 17:11:16 chef mysqld: pam_unix(mariadb:auth): conversation failed
Feb 13 17:11:16 chef mysqld: pam_unix(mariadb:auth): auth could not identify password for [oli]
Feb 13 17:11:16 chef mysqld: pam_winbind(mariadb:auth): getting password (0x00000388)
Feb 13 17:11:16 chef mysqld: pam_winbind(mariadb:auth): Could not retrieve user's password

# mysql --user=oli --host=localhost --password=wrong --plugin-dir=$PWD/lib/plugin
ERROR 1045 (28000): Access denied for user 'oli'@'localhost' (using password: NO)
Feb 13 17:11:30 chef mysqld: pam_unix(mariadb:auth): authentication failure; logname= uid=1001 euid=1001 tty= ruser= rhost=  user=oli
Feb 13 17:11:30 chef mysqld: pam_winbind(mariadb:auth): getting password (0x00000388)
Feb 13 17:11:30 chef mysqld: pam_winbind(mariadb:auth): pam_get_item returned a password
Feb 13 17:11:30 chef mysqld: pam_winbind(mariadb:auth): request wbcLogonUser failed: WBC_ERR_AUTH_ERROR, PAM error: PAM_USER_UNKNOWN (10), NTSTATUS: NT_STATUS_NO_SUCH_USER, Error message was: No such user

Add mysql user to the shadow group:

# ll /sbin/unix_chkpwd
-rwxr-sr-x 1 root shadow 35536 Mar 16  2016 /sbin/unix_chkpwd

# usermod -a -G shadow mysql

Connection tests:

# mysql --user=oli --host=localhost --password=right --plugin-dir=$PWD/lib/plugin

mysql> SELECT USER(), CURRENT_USER(), @@proxy_user;
+---------------+----------------+--------------+
| USER()        | CURRENT_USER() | @@proxy_user |
+---------------+----------------+--------------+
| oli@localhost | oli@localhost  | NULL         |
+---------------+----------------+--------------+

Taxonomy upgrade extras: 

MySQL Enterprise Backup Incremental Cumulative and Differential Backup

$
0
0

Preparing the MySQL Enterprise Administrator Training I found that the MySQL Enterprise Backup Incremental Backup is not described very well. Thus I tried it out and wrote down this how-to:

Incremental Differential Backup

incremental_backup_diff.png

Full Backup

mysqlbackup --user=root --backup-dir=/tape/full backup-and-apply-log
grep end_lsn /tape/full/meta/backup_variables.txt
end_lsn=2583666

Incremental Backups

mysqlbackup --user=root --incremental-backup-dir=/tape/inc1 --start-lsn=2583666 --incremental backup
grep end_lsn /tape/inc1/meta/backup_variables.txt
end_lsn=2586138

mysqlbackup --user=root --incremental-backup-dir=/tape/inc2 --start-lsn=2586138 --incremental backup
grep end_lsn /tape/inc2/meta/backup_variables.txt
end_lsn=2589328

mysqlbackup --user=root --incremental-backup-dir=/tape/inc3 --start-lsn=2589328 --incremental backup
grep end_lsn /tape/inc3/meta/backup_variables.txt
end_lsn=2592519

Binary Log Backups

cp /var/lib/binlog/binlog.* /tape/binlog/

Restore

This step will modify the original full backup!

mysqlbackup --incremental-backup-dir=/tape/inc1 --backup-dir=/tape/full apply-incremental-backup

mysqlbackup --incremental-backup-dir=/tape/inc2 --backup-dir=/tape/full apply-incremental-backup

mysqlbackup --incremental-backup-dir=/tape/inc3 --backup-dir=/tape/full apply-incremental-backup

mysqlbackup --user=root --datadir=/var/lib/mysql --backup-dir=/tape/full copy-back

Point-in-Time-Recovery

grep binlog_position /tape/inc3/meta/backup_variables.txt
/tape/inc3/meta/backup_variables.txt:binlog_position=binlog.000001:7731

cd /tape/binlog
mysqlbinlog --disable-log-bin --start-position=7731 binlog.000001 | mysql -uroot

Incremental Cumulative Backup

incremental_backup_cum.png

Full Backup

mysqlbackup --user=root --backup-dir=/tape/full backup-and-apply-log
grep end_lsn /tape/full/meta/backup_variables.txt
end_lsn=2602954

Incremental Backups

mysqlbackup --user=root --incremental-backup-dir=/tape/inc1 --start-lsn=2602954 --incremental backup

mysqlbackup --user=root --incremental-backup-dir=/tape/inc2 --start-lsn=2602954 --incremental backup

mysqlbackup --user=root --incremental-backup-dir=/tape/inc3 --start-lsn=2602954 --incremental backup

Binary Log Backups

cp /home/mysql/database/mysql-5.7/binlog/binlog.* /tape/binlog/

Restore

This step will modify the original full backup!

mysqlbackup --incremental-backup-dir=/tape/inc3 --backup-dir=/tape/full apply-incremental-backup

mysqlbackup --user=root --datadir=/var/lib/mysql --backup-dir=/tape/full copy-back

Point-in-Time-Recovery

grep binlog_position /tape/*/meta/backup_variables.txt
/tape/inc3/meta/backup_variables.txt:binlog_position=binlog.000001:7731

cd /tape/binlog
mysqlbinlog --disable-log-bin --start-position=7731 binlog.000001 | mysql -uroot

I very much dislike that during my restore the backup is modified. So if I do a mistake during restore my backup is gone and I am doomed.


Storing BLOBs in the database

$
0
0

We have sometimes discussions with our customers whether to store LOBs (Large Objects) in the database or not. To not rephrase the arguments again and again I have summarized them in the following lines.

The following items are more or less valid for all large data types (BLOB, TEXT and theoretically also for JSON and GIS columns) stored in a MySQL or MariaDB (or any other relational) database.

The idea of a relational table based data-store is to store structured data (numbers, data and short character strings) to have a quick write and read access to them.

And yes, you can also store other things like videos, huge texts (PDF, emails) or similar in a RDBMS but they are principally not designed for such a job and thus non optimal for the task. Software vendors implement such features not mainly because it makes sense but because users want it and the vendors want to attract users (or their managers) with such features (USP, Unique Selling Proposition). Here also one of my Mantras: Use the right tool for the right task:

right_tool_for_the_right_task.jpg

The main topics to discuss related to LOBs are: Operations, performance, economical reasons and technical limitations.

Disadvantages of storing LOBs in the database

  • The database will grow fast. Operations will become more costly and complicated.
  • Backup and restore will become more costly and complicated for the admin because of the increased size caused by LOBs.
  • Backup and restore will take longer because of the same reason.
  • Database and table management functions (OPTIMIZE, ALTER, etc.) will take longer on big LOB tables.
  • Smaller databases need less RAM/disk space and are thus cheaper.
  • Smaller databases fit better into your RAM and are thus potentially faster (RAM vs disk access).
  • RDBMS are a relatively slow technology (compared to others). Reading LOBs from the database is significantly slower than reading LOBs from a filer for example.
  • LOBs stored in the database will spoil your database cache (InnoDB Buffer Pool) and thus possibly slow down other queries (does not necessarily happen with more sophisticated RBDMS).
  • LOB size limitation of 1 Gbyte in reality (max_allowed_packet, theoretically limit is at 4 Gbyte) for MySQL/MariaDB.
  • Expensive, fast database store (RAID-10, SSD) is wasted for something which can be stored better on a cheap slow file store (RAID-5, HDD).
  • It is programmatically often more complicated to get LOBs from a database than from a filer (depends on your libraries).

Advantages of storing LOBs in the database

  • Atomicity between data and LOB is guaranteed by transactions (is it really in MySQL/MariaDB?).
  • There are no dangling links (reference from data to LOB) between data and LOB.
  • Data and LOB are from the same point in time and can be included in the same backup.
  • Data and LOB can be transferred simultaneously to other machines, by database replication or dump/restore.
  • Applications can use the same mechanism to get the data and the LOB. Remote access needs no separate file transfer for the LOB.

Conclusion

So basically you have to balance the advantages vs. the disadvantages of storing LOBs in the database and decided what arguments are more important in your case.

If you have some more good arguments pro or contra storing LOBs in the database please let me know.

Literature

Check also various articles on Google.

Taxonomy upgrade extras: 

Find evil developer habits with log_queries_not_using_indexes

$
0
0

Recently I switched on the MariaDB slow query logging flag log_queries_not_using_indexes just for curiosity on one of our customers systems:

mariadb> SHOW GLOBAL VARIABLES LIKE 'log_quer%';
+-------------------------------+-------+
| Variable_name                 | Value |
+-------------------------------+-------+
| log_queries_not_using_indexes | OFF   |
+-------------------------------+-------+

mariadb> SET GLOBAL log_queries_not_using_indexes = ON;

A tail -f on the MariaDB Slow Query Log caused a huge flickering on my screen.
I got to see about 5 times per second the following statement sequence in the Slow Query Log:

# User@Host: app_admin[app_admin] @  [192.168.1.42]  Id: 580195
# Query_time: 0.091731  Lock_time: 0.000028 Rows_sent: 273185 Rows_examined: 273185
SELECT LAST_INSERT_ID() FROM `placeholder`;
# Query_time: 0.002858  Lock_time: 0.000043 Rows_sent: 6856 Rows_examined: 6856
SELECT LAST_INSERT_ID() FROM `data`;

So at least 5 times 95 ms (5 x (92 + 3) = 475 ms) per 1000 ms (48%) where spent in these 2 statements which are running quite fast but do not use an index (long_query_time was set to 2 seconds).

So I estimate, that this load job can be speed up at least by factor 2 when using the LAST_INSERT_ID() function correctly not considering the possible reduction of network traffic (throughput and response time).

To show the problem I made a little test case:

mariadb> INSERT INTO test VALUES (NULL, 'Some data', NULL);

mariadb> SELECT LAST_INSERT_ID() from test;

+------------------+
| LAST_INSERT_ID() |
+------------------+
|          1376221 |
...
|          1376221 |
+------------------+
1048577 rows in set (0.27 sec)

The response time of this query will linearly grow with the amount of data as long as they fit into memory and the response time will explode as soon as the table does not fit into memory any more. In addition the network traffic would be reduced by about 8 Mbyte (1 Mio rows x BIGINT UNSIGNED (64-bit) + some header per row?) per second (6-8% of the network bandwidth of a 1 Gbit network link).

shell> ifconfig lo | grep bytes
          RX bytes:2001930826 (2.0 GB)  TX bytes:2001930826 (2.0 GB)
shell> ifconfig lo | grep bytes
          RX bytes:2027289745 (2.0 GB)  TX bytes:2027289745 (2.0 GB)

The correct way of doing the query would be:

mariadb> SELECT LAST_INSERT_ID();
+------------------+
| last_insert_id() |
+------------------+
|          1376221 |
+------------------+
1 row in set (0.00 sec)

The response time is below 10 ms.

So why is the first query taking so long an consuming so many resources? To get an answer to this question the MariaDB Optimizer can tell us more with the Query Execution Plan (QEP):

mariadb> EXPLAIN SELECT LAST_INSERT_ID() FROM test;
+------+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
| id   | select_type | table | type  | possible_keys | key     | key_len | ref  | rows    | Extra       |
+------+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
|    1 | SIMPLE      | test  | index | NULL          | PRIMARY | 4       | NULL | 1048577 | Using index |
+------+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+

mariadb> EXPLAIN FORMAT=JSON SELECT LAST_INSERT_ID() FROM test;
{
  "query_block": {
    "select_id": 1,
    "table": {
      "table_name": "test",
      "access_type": "index",
      "key": "PRIMARY",
      "key_length": "4",
      "used_key_parts": ["id"],
      "rows": 1048577,
      "filtered": 100,
      "using_index": true
    }
  }
}

The database does a Full Index Scan (FIS, other call it a Index Fast Full Scan (IFFS)) on the Primary Key (column id).

The Query Execution Plan of the second query looks as follows:

mariadb> EXPLAIN SELECT LAST_INSERT_ID();
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id   | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
|    1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | No tables used |
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+

mariadb> EXPLAIN FORMAT=JSON SELECT LAST_INSERT_ID();
{
  "query_block": {
    "select_id": 1,
    "table": {
      "message": "No tables used"
    }
  }
}

Galera Load Balancer the underestimated wallflower

$
0
0

There are some pretty sophisticated Load Balancers for Galera Clusters setups out in the market (ProxySQL, MaxScale, HAproxy, ...). They have many different exotic features. You can nearly do everything with them. But this comes at the cost of complexity. Non of them is simple any more.

A widely underestimated Load Balancer solution for Galera Cluster setups is the Galera Load Balancer from Codership. It is an simple Load Balancer solution which serves all of our daily needs when it comes to Galera Cluster. Unfortunately this product is not much promoted by the software vendor himself.

Installation of Galera Load Balancer

This starts with the installation. There are no packages ready to install. You have to compile Galera Load Balancer yourself. FromDual provides some compiled packages or can help you building and installing it.

You can get the Galera Load Balancer sources from Github. The binaries are built straight forward:

shell> git clone https://github.com/codership/glb
shell> cd glb/
shell> ./bootstrap.sh
shell> ./configure
shell> make
shell> make install

If you prefer a binary tar ball as I do, you can run the following commands instead of make install:

shell> TARGET=glb-1.0.1-linux-$(uname -m)
shell> mkdir -p ${TARGET}/sbin ${TARGET}/lib ${TARGET}/share/glb
shell> cp src/glbd ${TARGET}/sbin/
shell> cp src/.libs/libglb.a src/.libs/libglb.so* ${TARGET}/lib/
shell> cp files/* ${TARGET}/share/glb/
shell> cp README NEWS COPYING CONTRIBUTORS.txt CONTRIBUTOR_AGREEMENT.txt ChangeLog BUGS AUTHORS
shell> tar czf ${TARGET}.tar.gz ${TARGET}
shell> rm -rf ${TARGET}

Configuration of Galera Load Balancer

The Galera Load Balancer is configured in a file called glbd which must be located under /etc/sysconfig/gldb (Red Hat and its derivatives) or /etc/default/glbd (Debian and its derivatives). I did not find any option to tell Galera Load Balancer where to search for a configuration file.

The Galera Load Balancer parameters are documented here.

Starting and Stopping Galera Load Balancer

This means for me I have to specify all my parameters on the command line:

product/glb/sbin/glbd --threads 8 --max_conn 500 \
  --round --fifo /home/mysql/run/glbd.fifo --control 127.0.0.1:3333 \
  127.0.0.1:3306 \
  192.168.1.1:3306:1 192.168.1.2:3306:2 192.168.1.3:3306:1

An equivalent configuration file would look as follows:

#
# /etc/sysconfig/glbd.cfg
#
LISTEN_ADDR="127.0.0.1:3306"
CONTROL_ADDR="127.0.0.1:3333"
CONTROL_FIFO="/home/mysql/run/glbd.fifo"
THREADS="8"
MAX_CONN="500"
DEFAULT_TARGETS="192.168.1.1:3306:1 192.168.1.2:3306:2 192.168.1.3:3306:1"
OTHER_OPTIONS="--round"

Stopping Galera Load Balancer is simple:

killall glbd

Galera Load Balancer operations

Beside starting and stopping Galera Load Balancer you also want to look into it. This can be done with the following 2 commands:

echo getinfo | nc -q 1 127.0.0.1 3333
echo getstats | nc -q 1 127.0.0.1 3333

Or if you want to have it in a more top/vmstat like style:

watch -n 1 "echo getstats | nc -q 1 127.0.0.1 3333"

watch -n 1 -d "echo getinfo | nc -q 1 127.0.0.1 3333"

More interesting are operations like draining and undraining a Galera Cluster node from the Galera Load Balancer. To drain a Galera Cluster node for example for maintenance (kernel upgrade?) you can run the following command:

echo "192.168.1.2:3306:0" | nc 127.0.0.1 3333

To undrain the node again it works like this:

echo "192.168.1.2:3306:2" | nc 127.0.0.1 3333

Unfortunately Galera Load Balancer does not memorize the weight (:2).

If you want to remove or add a node from/to the Galera Load Balancer this works as follows:

echo "192.168.1.2:3306:-1" | nc 127.0.0.1 3333

echo "192.168.1.2:3306:1" | nc 127.0.0.1 3333

Further Galera Load Balancer operation tasks you can find in the documentation.

MariaDB master/master GTID based replication with keepalived VIP

$
0
0

Some of our customers still want to have old-style MariaDB master/master replication clusters. Time goes by, new technologies appear but some old stuff still remains.

The main problem in a master/master replication set-up is to make the service highly available for the application (applications typically cannot deal with more than one point-of-contact). This can be achieved with a load balancer (HAproxy, Galera Load Balancer (GLB), ProxySQL or MaxScale) in front of the MariaDB master/master replication cluster. But the load balancer by it-self should also become highly available. And this is typically achieved by a virtual IP (VIP) in front of one of the load balancers. To make operations of the VIP more handy the VIP is controlled by a service like keepalived or corosync.

M/M with LB and keepalived

Because I like simple solutions (I am a strong believer in the KISS principle) I thought about avoiding the load balancer in the middle and attach the VIP directly to the master/master replication servers and let them to be controlled by keepalived as well.

M/M with keepalived

Important: A master/master replication set-up is vulnerable to split-brain situations. Neither keepalived nor the master/master replication helps you to avoid conflicts and in any way to prevent this situation. If you are sensitive to split-brain situations you should look for Galera Cluster. Keepalived is made for stateless services like load balancers, etc. but not databases.

Set-up a MariaDB master/master replication cluster

Because most of the Linux distributions have a bit old versions of software delivered we use the MariaDB 10.2 repository from the MariaDB website:

#
# /etc/yum.repos.d/MariaDB-10.2.repo 
#
# MariaDB 10.2 CentOS repository list - created 2017-11-08 20:32 UTC
# http://downloads.mariadb.org/mariadb/repositories/
#
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.2/centos7-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1

Then we install the MariaDB server and start it:

shell> yum makecache
shell> yum install MariaDB-server MariaDB-client
shell> systemctl start mariadb
shell> systemctl enabled mariadb

For the MariaDB master/master replication set-up configuration we use the following parameters:

#
# /etc/my.cnf
#

[mysqld]

server_id                = 1           # 2 on the other node
log_bin                  = binlog-m1   # binlog-m2 on the other node
log_slave_updates        = 1

gtid_domain_id           = 1           # 2 on the other node
gtid_strict_mode         = On

auto_increment_increment = 2
auto_increment_offset    = 1           # 2 on the other node

read_only                = On          # super_read_only for MySQL 5.7 and newer

Then we close the master/master replication ring according to: Starting with empty server.

mariadb> SET GLOBAL gtid_slave_pos = "";
mariadb> CHANGE MASTER TO master_host="192.168.56.101", master_user="replication"
                        , master_use_gtid=current_pos;
mariadb> START SLAVE;

Installing keepalived

Literature:


The next step is to install and configure keepalived. This can be done as follows:

shell> yum install keepalived
shell> systemctl enable keepalived

Important: In my tests I got crashes and core dumps with keepalived which disappeared after a full upgrade of CentOS 7.

Configuring keepalived

The most important part is the keepalived configuration file:

#
# /etc/keepalived/keepalived.conf
#

global_defs {

  notification_email {

    root@localhost
    dba@example.com
  }

  notification_email_from root@master1   # master2 on the other node
  smtp_server localhost 25

  router_id MARIADB_MM
  enable_script_security
}


# Health checks

vrrp_script chk_mysql {

  script "/usr/sbin/pidof mysqld"
  weight 2     # Is relevant for the diff in priority
  interval 1   # every ... seconds
  timeout 3    # script considered failed after ... seconds
  fall 3       # number of failures for K.O.
  rise 1       # number of success for OK
}

vrrp_script chk_failover {

  script "/etc/keepalived/chk_failover.sh"
  weight -4    # Is relevant for the diff in priority
  interval 1   # every ... seconds
  timeout 1    # script considered failed after ... seconds
  fall 1       # number of failures for K.O.
  rise 1       # number of success for OK
}


# Main configuration

vrrp_instance VI_MM_VIP {

  state MASTER           # BACKUP on the other side

  interface enp0s9       # private heartbeat interface

  priority 100           # Higher means: elected first (BACKUP: 99)
  virtual_router_id 42   # ID for all nodes of Cluster group

  debug 0                # 0 .. 4, seems not to work?

  unicast_src_ip 192.168.56.101   # Our private IP address
  unicast_peer {
    192.168.56.102       # Peers private IP address
  }


  # For keepalived communication

  authentication {
    auth_type PASS
    auth_pass Secr3t!
  }


  # VIP to move around

  virtual_ipaddress {

    192.168.1.99/24 dev enp0s8   # public interface for VIP
  }


  # Check health of local system. See vrrp_script above.

  track_script {
    chk_mysql
    # If File /etc/keepalived/failover is touched failover is triggered
    # Similar can be reached when priority is lowered followed by a reload
    chk_failover
  }

  # When node becomes MASTER this script is triggered
  notify_master "/etc/keepalived/keepalived_master.sh --user=root --password= --wait=yes --variable=read_only"
  # When node becomes SLAVE this script is triggered
  notify_backup "/etc/keepalived/keepalived_backup.sh --user=root --password= --kill=yes --variable=read_only"
  # Possibly fault and stop should also call keepalived_backup.sh to be on the safe side...
  notify_fault "/etc/keepalived/keepalived_fault.sh arg1 arg2"
  notify_stop "/etc/keepalived/keepalived_stop.sh arg1 arg2"
  # ANY state transit is triggered
  notify /etc/keepalived/keepalived_notify.sh

  smtp_alert   # send notification during state transit
}

With the command:

shell> systemctl restart keepalived

the service is started and/or the configuration is reloaded.

The scripts we used in the configuration file are the following:

chk_failover.sh
keepalived_backup.sh
keepalived_fault.sh
keepalived_master.sh
keepalived_notify.sh
keepalived_stop.sh

#!/bin/bash
#
# /etc/keepalived/keepalived_notify.sh
#

TYPE=${1}
NAME=${2}
STATE=${3}
PRIORITY=${4}

TS=$(date '+%Y-%m-%d_%H:%M:%S')
LOG=/etc/keepalived/keepalived_notify.log

echo $TS $0 $@ >>${LOG}

#!/bin/bash
#
# /etc/keepalived/chk_failover.sh
#

/usr/bin/stat /etc/keepalived/failover 2>/dev/null 1>&2
if [ ${?} -eq 0 ] ; then
  exit 1
else
  exit 0
fi

To make MariaDB master/master replication more robust against replication problems we took the following (configurable) actions on the database side:

Getting the MASTER role:

  • Waiting for catch-up replication
  • Make the MariaDB instance read/write

Getting the BACKUP role:

  • Make the MariaDB instance read-only
  • Kill all open connections

Testing scenarios

The following scenarios where tested under load (insert_test.sh):

  • Intentional fail-over for maintenance:
    shell> touch /etc/keepalived/failover
    shell> rm -f /etc/keepalived/failover
    
  • Stopping keepalived:
    shell> systemctl stop keepalived
    shell> systemctl start keepalived
    
  • Stopping MariaDB node:
    shell> systemctl stop mariadb
    shell> systemctl start mariadb
    
  • Reboot server:
    shell> reboot
    
  • Simulation of split-brain:
    shell> ip link set enp0s9 down
    shell> ip link set enp0s9 up
    

Problems

Problems we faced during set-up and testing were:

  • SElinux/AppArmor
  • Firewall

Keepalived controlling 2 virtual IPs

A second scenario we wanted to build is a MariaDB master/master GTID based replication cluster with 2 VIP addresses. This is to achieve either a read-only VIP and a read/write VIP or to have half of the load on one master and half of the load on the other master:

M/M with keepalived and 2 VIPs

For this scenario we used the same scripts but a slightly different keepalived configuration:

#
# /etc/keepalived/keepalived.conf
#

global_defs {

  notification_email {

    root@localhost
    dba@example.com
  }

  notification_email_from root@master1   # master2 on the other node
  smtp_server localhost 25

  router_id MARIADB_MM
  enable_script_security
}


# Health checks

vrrp_script chk_mysql {

  script "/usr/sbin/pidof mysqld"
  weight 2     # Is relevant for the diff in priority
  interval 1   # every ... seconds
  timeout 3    # script considered failed after ... seconds
  fall 3       # number of failures for K.O.
  rise 1       # number of success for OK
}

vrrp_script chk_failover {

  script "/etc/keepalived/chk_failover.sh"
  weight -4    # Is relevant for the diff in priority
  interval 1   # every ... seconds
  timeout 1    # script considered failed after ... seconds
  fall 1       # number of failures for K.O.
  rise 1       # number of success for OK
}


# Main configuration

vrrp_instance VI_MM_VIP1 {

  state MASTER           # BACKUP on the other side

  interface enp0s9       # private heartbeat interface

  priority 100           # Higher means: elected first (BACKUP: 99)
  virtual_router_id 42   # ID for all nodes of Cluster group

  unicast_src_ip 192.168.56.101   # Our private IP address
  unicast_peer {
    192.168.56.102       # Peers private IP address
  }


  # For keepalived communication

  authentication {
    auth_type PASS
    auth_pass Secr3t!
  }


  # VIP to move around

  virtual_ipaddress {

    192.168.1.99/24 dev enp0s8   # public interface for VIP
  }


  # Check health of local system. See vrrp_script above.

  track_script {
    chk_mysql
    chk_failover
  }

  # ANY state transit is triggered
  notify /etc/keepalived/keepalived_notify.sh

  smtp_alert   # send notification during state transit
}

vrrp_instance VI_MM_VIP2 {

  state BACKUP           # MASTER on the other side

  interface enp0s9       # private heartbeat interface

  priority 99            # Higher means: elected first (MASTER: 100)
  virtual_router_id 43   # ID for all nodes of Cluster group

  unicast_src_ip 192.168.56.101   # Our private IP address
  unicast_peer {
    192.168.56.102       # Peers private IP address
  }


  # For keepalived communication

  authentication {
    auth_type PASS
    auth_pass Secr3t!
  }


  # VIP to move around

  virtual_ipaddress {

    192.168.1.98/24 dev enp0s8   # public interface for VIP
  }


  # Check health of local system. See vrrp_script above.

  track_script {
    chk_mysql
    chk_failover
  }

  # ANY state transit is triggered
  notify /etc/keepalived/keepalived_notify.sh

  smtp_alert   # send notification during state transit
}

First Docker steps with MySQL and MariaDB

$
0
0

The Docker version of the distributions are often quite old. On Ubuntu 16.04 for example:

shell> docker --version 
Docker version 1.13.1, build 092cba3

But the current docker version is 17.09.0-ce (2017-09-26). It seems like they have switched from the old version schema x.y.z to the new year.month.version version schema in February/March 2017.

Install Docker CE Repository

Add the Docker's official PGP key:

shell> curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
OK

Add the Docker repository:

shell> echo "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"> /etc/apt/sources.list.d/docker.list
shell> apt-get update

Install or upgrade Docker:

shell> apt-get install docker-ce
shell> docker --version
Docker version 17.09.0-ce, build afdb6d4

To test your Docker installation run:

shell> docker run --rm hello-world

Add Docker containers for MariaDB, MySQL and MySQL Enterprise Edition

First we want to see what Docker containers are available:

shell> docker search mysql --no-trunc --filter=stars=100
NAME               DESCRIPTION                                                                                         STARS OFFICIAL AUTOMATED
mysql              MySQL is a widely used, open-source relational database management system (RDBMS).                  5273  [OK]
mariadb            MariaDB is a community-developed fork of MySQL intended to remain free under the GNU GPL.           1634  [OK]
mysql/mysql-server Optimized MySQL Server Docker images. Created, maintained and supported by the MySQL team at Oracle 368            [OK]
percona            Percona Server is a fork of the MySQL relational database management system created by Percona.     303   [OK]
...

OK. It seems like MySQL Server Enterprise Edition is missing. So we have to create an account on Docker Store and get the MySQL Server Enterprise Edition Image from there:

shell> docker login --username=fromdual
Password:
Login Succeeded

Unfortunately one can still not see MySQL Server Enterprise Edition.

But we can try anyway:

shell> docker pull store/oracle/mysql-enterprise-server:5.7
shell> docker logout
shell> docker pull mysql
shell> docker pull mariadb
shell> docker pull mysql/mysql-server

To see what is going on on your local Docker registry you can type:

shell> docker images
REPOSITORY                           TAG    IMAGE ID     CREATED       SIZE
mariadb                              latest abcee1d29aac 8 days ago    396MB
mysql                                latest 5709795eeffa 2 weeks ago   408MB
mysql/mysql-server                   latest a3ee341faefb 5 weeks ago   246MB
store/oracle/mysql-enterprise-server 5.7    41bf2fa0b4a1 4 months ago  244MB
hello-world                          latest 48b5124b2768 10 months ago 1.84kB

I personally do not like that all those images which are tagged with latest because I want a clear control over what version is used. MariaDB and MySQL community server have implemented this quite nicely but not MySQL Enterprise Edition:

shell> docker pull mariadb:10.0
shell> docker pull mariadb:10.0.23
shell> docker pull mysql:8.0
shell> docker pull mysql:8.0.3

docker images | sort
REPOSITORY                           TAG     IMAGE ID     CREATED       SIZE
hello-world                          latest  48b5124b2768 10 months ago 1.84kB
mariadb                              10.0.23 93631b528e67 21 months ago 305MB
mariadb                              10.0    eecd58425049 8 days ago    337MB
mariadb                              latest  abcee1d29aac 8 days ago    396MB
mysql                                8.0.3   e691422324d8 2 weeks ago   343MB
mysql                                8.0     e691422324d8 2 weeks ago   343MB
mysql                                latest  5709795eeffa 2 weeks ago   408MB
mysql/mysql-server                   latest  a3ee341faefb 5 weeks ago   246MB
store/oracle/mysql-enterprise-server 5.7     41bf2fa0b4a1 4 months ago  244MB

Run a MariaDB server container

Start a new Docker container from the MariaDB image by running:

shell> CONTAINER_NAME=mariadb
shell> CONTAINER_IMAGE=mariadb
shell> TAG=latest
shell> MYSQL_ROOT_PASSWORD=Secret-123
shell> MYSQL_ROOT_USER=root

shell> docker run \
  --name=${CONTAINER_NAME} \
  --detach \
  --env=MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} \
  ${CONTAINER_IMAGE}:${TAG}

shell> docker ps
CONTAINER ID IMAGE          COMMAND                CREATED        STATUS        PORTS    NAMES
60d7b6de7ed1 mariadb:latest "docker-entrypoint..." 24 seconds ago Up 23 seconds 3306/tcp mariadb

shell> docker logs ${CONTAINER_NAME}

shell> docker exec \
  --interactive \
  --tty \
  ${CONTAINER_NAME} \
  mysql --user=${MYSQL_ROOT_USER} --password=${MYSQL_ROOT_PASSWORD} --execute="status"

shell> docker image tag mariadb:latest mariadb:10.2.10

shell> docker exec --interactive \
  --tty \
  ${CONTAINER_NAME} \
  bash 

shell> docker stop ${CONTAINER_NAME}
shell> docker rm ${CONTAINER_NAME}

Run a MySQL Community server container

shell> CONTAINER_NAME=mysql
shell> CONTAINER_IMAGE=mysql/mysql-server
shell> TAG=latest
shell> MYSQL_ROOT_PASSWORD=Secret-123

shell> docker run \
  --name=${CONTAINER_NAME} \
  --detach \
  --env=MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} \
  ${CONTAINER_IMAGE}:${TAG}

shell> docker stop ${CONTAINER_NAME}
shell> docker rm ${CONTAINER_NAME}

Run a MySQL Server Enterprise Edition container

shell> CONTAINER_NAME=mysql-ee
shell> CONTAINER_IMAGE=store/oracle/mysql-enterprise-server
shell> TAG=5.7
shell> MYSQL_ROOT_PASSWORD=Secret-123

shell> docker run \
  --name=${CONTAINER_NAME} \
  --detach \
  --env=MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} \
  ${CONTAINER_IMAGE}:${TAG}

shell> docker ps --all
CONTAINER ID IMAGE                                    COMMAND                CREATED        STATUS                  PORTS               NAMES
0cb4e6a8a621 store/oracle/mysql-enterprise-server:5.7 "/entrypoint.sh my..." 37 seconds ago Up 36 seconds (healthy) 3306/tcp, 33060/tcp mysql-ee
1832b98da6ef mysql:latest                             "docker-entrypoint..." 6 minutes ago  Up 6 minutes            3306/tcp            mysql
60d7b6de7ed1 mariadb:latest                           "docker-entrypoint..." 21 minutes ago Up 21 minutes           3306/tcp            mariadb

All my 3 docker containers are currently running as root:

shell> ps -ef | grep docker
root 13177     1 20:20 ? 00:00:44 /usr/bin/dockerd -H fd://
root 13186 13177 20:20 ? 00:00:04 docker-containerd -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --metrics-interval=0 --start-timeout 2m --state-dir /var/run/docker/libcontainerd/containerd --shim docker-containerd-shim --runtime docker-runc
root 24004 13186 21:41 ? 00:00:00 docker-containerd-shim 60d7b6de7ed1ff62b67e66c6effce0094fd60e9565ede65fa34e188b636c54ec /var/run/docker/libcontainerd/60d7b6de7ed1ff62b67e66c6effce0094fd60e9565ede65fa34e188b636c54ec docker-runc
root 26593 13186 21:56 ? 00:00:00 docker-containerd-shim 1832b98da6ef7459c33181e9b9ddd89a4136c3b2676335bcbbb533389cbf6219 /var/run/docker/libcontainerd/1832b98da6ef7459c33181e9b9ddd89a4136c3b2676335bcbbb533389cbf6219 docker-runc
root 27714 13186 22:02 ? 00:00:00 docker-containerd-shim 0cb4e6a8a62103b66164ccddd028217bb4012d8a6aad1f62d3ed6ae71e1a38b4 /var/run/docker/libcontainerd/0cb4e6a8a62103b66164ccddd028217bb4012d8a6aad1f62d3ed6ae71e1a38b4 docker-runc

But the user running the process IN the container is not root:

shell> docker exec \
  --interactive \
  --tty \
  ${CONTAINER_NAME} \
  grep ^Uid /proc/1/status
Uid:    27      27      27      27

shell> docker exec \
  --interactive \
  --tty \
  ${CONTAINER_NAME} \
  bash -c "id 27"
uid=27(mysql) gid=27(mysql) groups=27(mysql)

Run a Docker container from mysql user

shell> id
uid=1001(mysql) gid=1001(mysql) groups=1001(mysql)
shell> docker images
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.32/images/json: dial unix /var/run/docker.sock: connect: permission denied

shell> sudo adduser mysql docker
Adding user `mysql' to group `docker' ...
Adding user mysql to group docker
Done.

Taxonomy upgrade extras: 

Galera Cluster and Antivirus Scanner on Linux

$
0
0

Today we had to investigate in a very strange behaviour of IST and SST on a MariaDB Galera Cluster.

The symptom was, that some Galera Cluster nodes took a very long time to start. Up to 7 minutes. So the customer was concluding that the Galera Cluster node does an SST instead of an IST and was asking why the SST happens.

It have to be mentioned here, that the MariaDB error log is very confusing about whether it is an SST or an IST. So the customer was confused and concluded, that MariaDB Galera Cluster was doing an SST instead of IST.

Further confusing was that this behaviour was not consistently on all 3 nodes and not consistently on the 3 stages production, test and integration.

First we had to clear if the Galera node was doing an IST or an SST to exclude problems with Galera Cache or event Bugs in MariaDB Galera Cluster. For this we were running our famous insert_test.sh and did some node restarts with forcing SST and without.

As a Galera Cluster operator you must mandatorily be capable to determine which one of both State Transfers happens from the MariaDB error log:

MariaDB Error Log with IST on Joiner

2017-12-12 22:29:33 140158145914624 [Note] WSREP: Shifting OPEN -> PRIMARY (TO: 204013)
2017-12-12 22:29:33 140158426741504 [Note] WSREP: State transfer required: 
        Group state: e2fbbca5-df26-11e7-8ee2-bb61f8ff3774:204013
        Local state: e2fbbca5-df26-11e7-8ee2-bb61f8ff3774:201439
2017-12-12 22:29:33 140158426741504 [Note] WSREP: New cluster view: global state: e2fbbca5-df26-11e7-8ee2-bb61f8ff3774:204013, view# 7: Primary, number of nodes: 3, my index: 2, protocol version 3
2017-12-12 22:29:33 140158426741504 [Warning] WSREP: Gap in state sequence. Need state transfer.
2017-12-12 22:29:33 140158116558592 [Note] WSREP: Running: 'wsrep_sst_rsync --role 'joiner' --address '127.0.0.1' --datadir '/home/mysql/database/magal-101-b/data/'  --defaults-file '/home/mysql/database/magal-101-b/etc/my.cnf'  --parent '16426' --binlog '/home/mysql/database/magal-101-b/binlog/laptop4_magal-101-b__binlog''
2017-12-12 22:29:33 140158426741504 [Note] WSREP: Prepared SST request: rsync|127.0.0.1:4444/rsync_sst
2017-12-12 22:29:33 140158426741504 [Note] WSREP: REPL Protocols: 7 (3, 2)
2017-12-12 22:29:33 140158426741504 [Note] WSREP: Assign initial position for certification: 204013, protocol version: 3
2017-12-12 22:29:33 140158203852544 [Note] WSREP: Service thread queue flushed.
2017-12-12 22:29:33 140158426741504 [Note] WSREP: IST receiver addr using tcp://127.0.0.1:5681
2017-12-12 22:29:33 140158426741504 [Note] WSREP: Prepared IST receiver, listening at: tcp://127.0.0.1:5681
2017-12-12 22:29:33 140158145914624 [Note] WSREP: Member 2.0 (Node B) requested state transfer from 'Node C'. Selected 1.0 (Node C)(SYNCED) as donor.
2017-12-12 22:29:33 140158145914624 [Note] WSREP: Shifting PRIMARY -> JOINER (TO: 204050)
2017-12-12 22:29:33 140158426741504 [Note] WSREP: Requesting state transfer: success, donor: 1
2017-12-12 22:29:33 140158426741504 [Note] WSREP: GCache history reset: old(e2fbbca5-df26-11e7-8ee2-bb61f8ff3774:0) -> new(e2fbbca5-df26-11e7-8ee2-bb61f8ff3774:204013)
2017-12-12 22:29:33 140158145914624 [Note] WSREP: 1.0 (Node C): State transfer to 2.0 (Node B) complete.
2017-12-12 22:29:33 140158145914624 [Note] WSREP: Member 1.0 (Node C) synced with group.
WSREP_SST: [INFO] Joiner cleanup. rsync PID: 16663 (20171212 22:29:34.474)
WSREP_SST: [INFO] Joiner cleanup done. (20171212 22:29:34.980)
2017-12-12 22:29:34 140158427056064 [Note] WSREP: SST complete, seqno: 201439
2017-12-12 22:29:35 140158427056064 [Note] WSREP: Signalling provider to continue.
2017-12-12 22:29:35 140158427056064 [Note] WSREP: SST received: e2fbbca5-df26-11e7-8ee2-bb61f8ff3774:201439
2017-12-12 22:29:35 140158426741504 [Note] WSREP: Receiving IST: 2574 writesets, seqnos 201439-204013
2017-12-12 22:29:35 140158426741504 [Note] WSREP: IST received: e2fbbca5-df26-11e7-8ee2-bb61f8ff3774:204013
2017-12-12 22:29:35 140158145914624 [Note] WSREP: 2.0 (Node B): State transfer from 1.0 (Node C) complete.
2017-12-12 22:29:35 140158145914624 [Note] WSREP: Shifting JOINER -> JOINED (TO: 204534)
2017-12-12 22:29:35 140158145914624 [Note] WSREP: Member 2.0 (Node B) synced with group.
2017-12-12 22:29:35 140158145914624 [Note] WSREP: Shifting JOINED -> SYNCED (TO: 204535)
2017-12-12 22:29:35 140158426741504 [Note] WSREP: Synchronized with group, ready for connections

MariaDB Error Log with SST on Joiner

2017-12-12 22:32:15 139817123833600 [Note] WSREP: Shifting OPEN -> PRIMARY (TO: 239097)
2017-12-12 22:32:15 139817401395968 [Note] WSREP: State transfer required: 
        Group state: e2fbbca5-df26-11e7-8ee2-bb61f8ff3774:239097
        Local state: 00000000-0000-0000-0000-000000000000:-1
2017-12-12 22:32:15 139817401395968 [Note] WSREP: New cluster view: global state: e2fbbca5-df26-11e7-8ee2-bb61f8ff3774:239097, view# 9: Primary, number of nodes: 3, my index: 2, protocol version 3
2017-12-12 22:32:15 139817401395968 [Warning] WSREP: Gap in state sequence. Need state transfer.
2017-12-12 22:32:15 139817094477568 [Note] WSREP: Running: 'wsrep_sst_rsync --role 'joiner' --address '127.0.0.1' --datadir '/home/mysql/database/magal-101-b/data/'  --defaults-file '/home/mysql/database/magal-101-b/etc/my.cnf'  --parent '25291' --binlog '/home/mysql/database/magal-101-b/binlog/laptop4_magal-101-b__binlog''
2017-12-12 22:32:15 139817401395968 [Note] WSREP: Prepared SST request: rsync|127.0.0.1:4444/rsync_sst
2017-12-12 22:32:15 139817401395968 [Note] WSREP: REPL Protocols: 7 (3, 2)
2017-12-12 22:32:15 139817401395968 [Note] WSREP: Assign initial position for certification: 239097, protocol version: 3
2017-12-12 22:32:15 139817178507008 [Note] WSREP: Service thread queue flushed.
2017-12-12 22:32:15 139817401395968 [Warning] WSREP: Failed to prepare for incremental state transfer: Local state UUID (00000000-0000-0000-0000-000000000000) does not match group state UUID (e2fbbca5-df26-11e7-8ee2-bb61f8ff3774): 1 (Operation not permitted)
         at galera/src/replicator_str.cpp:prepare_for_IST():482. IST will be unavailable.
2017-12-12 22:32:15 139817123833600 [Note] WSREP: Member 2.0 (Node B) requested state transfer from 'Node C'. Selected 1.0 (Node C)(SYNCED) as donor.
2017-12-12 22:32:15 139817123833600 [Note] WSREP: Shifting PRIMARY -> JOINER (TO: 239136)
2017-12-12 22:32:15 139817401395968 [Note] WSREP: Requesting state transfer: success, donor: 1
2017-12-12 22:32:15 139817401395968 [Note] WSREP: GCache history reset: old(00000000-0000-0000-0000-000000000000:0) -> new(e2fbbca5-df26-11e7-8ee2-bb61f8ff3774:239097)
2017-12-12 22:32:17 139817123833600 [Note] WSREP: 1.0 (Node C): State transfer to 2.0 (Node B) complete.
2017-12-12 22:32:17 139817123833600 [Note] WSREP: Member 1.0 (Node C) synced with group.
WSREP_SST: [INFO] Joiner cleanup. rsync PID: 25520 (20171212 22:32:17.846)
WSREP_SST: [INFO] Joiner cleanup done. (20171212 22:32:18.352)
2017-12-12 22:32:18 139817401710528 [Note] WSREP: SST complete, seqno: 239153
2017-12-12 22:32:18 139817132226304 [Note] WSREP: (ebfd9e9c, 'tcp://127.0.0.1:5680') turning message relay requesting off
2017-12-12 22:32:22 139817401710528 [Note] WSREP: Signalling provider to continue.
2017-12-12 22:32:22 139817401710528 [Note] WSREP: SST received: e2fbbca5-df26-11e7-8ee2-bb61f8ff3774:239153
2017-12-12 22:32:22 139817123833600 [Note] WSREP: 2.0 (Node B): State transfer from 1.0 (Node C) complete.
2017-12-12 22:32:22 139817123833600 [Note] WSREP: Shifting JOINER -> JOINED (TO: 239858)
2017-12-12 22:32:22 139817123833600 [Note] WSREP: Member 2.0 (Node B) synced with group.
2017-12-12 22:32:22 139817123833600 [Note] WSREP: Shifting JOINED -> SYNCED (TO: 239866)
2017-12-12 22:32:22 139817401395968 [Note] WSREP: Synchronized with group, ready for connections

After we cleared that it really was an IST and that it was not a SST because of some other reasons the question rose: Why does an IST of only a few thousand transactions was taking 420 seconds. And this was not always the case...

So we were looking with top at the Donor and the Joiner during IST and we found that on the Donor node the Antivirus software was heavily using CPU (2 x 50%) and otherwise the system was doing nothing for a while and then suddenly started to transfer data over the network (possibly IST?).
Later we found, that the MariaDB datadir (/var/lib/mysql) was not excluded from the Antivirus software. And finally it looks like the Antivirus software was not properly configured by its Master server because the Antivirus software agent was from a cloned VM and not reinitialized. So the Antivirus Master server seems to be confused because there are 2 Antivirus software agents with the same ID.

Another very surprising situation which we did not expect was, that IST was much heavier influenced by the Antivirus software than SST. SST finished in a few seconds while IST took 420 seconds.

Conclusion: Be careful when using Antivirus software in combination with MariaDB Galera Cluster databases and exclude at least all database directories from virus scanning. If you want to be sure to avoid side effects (noisy neighbours) disable the Antivirus software on the database server at all and make sure by other means, that no virus is reaching your precious MariaDB Galera Cluster...

Oracle releases MySQL security vulnerability fixes 2018-01

$
0
0

As in every quarter of the year Oracle has released yesterday its recommendation for the MySQL security updates. This is called, in Oracle terminology, Critical Patch Update (CPU) Advisory.

This CPU is published for all Oracle products. But FromDual is only interested in MySQL related topics. So let us concentrate on those.

This time 25 fixes with a maximum score of 8.1 (out of 10.0) were published.

6 of theses 25 vulnerabilities are exploitable remotely over the network without authentication (no user credentials required)!

The following MySQL products are affected:

  • MySQL Enterprise Monitor (3.3.6.3293 and before, 3.4.4.4226 and before, 4.0.0.5135 and before)
  • MySQL Connector/Net (6.9.9. and before, 6.10.4 and before)
  • MySQL Connector/ODBC (5.3.9. and before)
  • MySQL Server (5.5.58 and before, 5.6.38 and before, 5.7.19 and before)

It is recommended to upgrade your MySQL products to close the security vulnerabilities.

FromDual upgrade decision aid

Because such security updates are published quarterly and some of our customers have dozens to hundreds of MySQL installations this would end up in a never ending story where you are continuously upgrading MySQL database servers and other products.

This led to idea to create an upgrade decision aid to decide if you have to upgrade to this CPU or not.

The following questions can be asked:

  • How exposed is your database?
    Databases can be located in various network segments. It is not recommended to expose databases directly to the internet. Databases are either installed in demilitarized zones (DMZ) with no direct access from the internet or in the companies private network (only company employees should be able to access the database) or even specialized secure networks (only a limited number of specific employees can access this network).
  • How critical are your data?
    Some data are more interesting or critical, some data are less interesting or critical. Interesting data are: User data (user name and password), customer data (profiles, preferences, etc.), financial data (credit cards) and health care data (medical data). Systems containing such data are more critical than others. You can also ask: How sever is it if such data leak?
  • How broad is the user base able to access the database?
    How many employees do you have in your company? How many contractors do you have in your company? How many employees have physical access to the database server? How good is the mood of those people?
    How good are the user credentials to protect your database? Do you have shared passwords or no passwords at all? Do you have an account management (expiring old accounts, rotate passwords from time to time)?
    How much do you trust your users? Do you trust all your employees? Do you trust only admins? Or do you not even trust your admins?
  • How severe are the security vulnerabilities?
    You can define a threshold of severity of the vulnerabilities above you want to take actions. According to your criticality you can take actions for example as follows: Greater or equal than 7.5 if you have less critical data. Greater or equal than 6.0 if you have critical data.
  • Can the vulnerability be use from remote (over the network) and does it need a user authentication to exploit the vulnerability? What products (MySQL Enterprise Monitor, MySQL Server, MySQL Connectors) and what modules (Apache/Tomcat, .Net Connector, Partitioning, Stored Procedures, InnoDB, DDL, GIS, Optimizer, ODBC, Replication, DML, Performance Schema) are affected?

Depending on your readiness to take a risk you get now answers to decide if you have to take actions or not.

Some examples

  • Situation: Your database is exposed directly to the internet or you forgot to install some firewall rules to protect your MySQL port.
    Analysis: You are probably affected by CVE-2018-2696 and CVE-2017-3737 (score 5.9 and 7.5). So you passed the threshold for non-critical data (7.5) and nearly passed the threshold for critical data (6.0). These vulnerabilities allow attacks over the network without user authentication.
    Action: Immediate upgrade is recommended. Mid-term action: Install firewall rules to protect your MySQL to avoid access from remote and/or do not expose databases directly to the internet.
  • Situation: Your database is located in the intranet zone. You have slack user/password policies and you have many employees and also many contractors from foreign countries working on various projects. And you have very sensitive/interesting financial data stored in your database.
    Analysis: Many people, not all of them are really trusted, have network access to the database. It is quite possible that passwords have been shared or people have passwords for projects they are not working for any more. You are affected by nearly all of the vulnerabilities (network).
    Action: You should plan an upgrade soon. Mid-term action: Try to restrict access to the databases and implement some password policy rules (no shared passwords, password expiration, account locking etc.).
  • Situation: Your highly critical databases are located in a specially secured network and only applications, Linux admins and DBAs have access to this network. And you completely trust those people.
    Analysis: Your threshold is 6.0 and (unauthenticated) attack over the network is not possible. There are some vulnerabilities of which you are affected but the database is only accessed by an application. So those vulnerabilities cannot be exploited easily.
    Action: You possibly can ignore this CPU for the MySQL database this time. But you have a vulnerability in the .Net Connector (Connector/Net). If an attacker exploits the vulnerability on the Connector he possibly can get access to the data. So you have to upgrade the Connector of your application accessing the database.

If you follow the ideas of this aid you will probably have one or two upgrades a year. And this you should do anyway just to stay up to date...

See also Common Vulnerability Scoring System Version 3.0 Calculator.

Taxonomy upgrade extras: 

Advanced MySQL and MariaDB training in Cologne 2018

$
0
0

End of February, from February 26 to March 2 (5 days), FromDual offers an additional training for DBAs and DevOps: our most visited Advanced MySQL and MariaDB training.

This training is hold in the training facilities of the FromDual training partner GFU Cyrus GmbH in Cologne-Deutz (Germany).

There are already enough registrations so it is certain the training will take place. But there are still free places for at least 3 additional participants.

The training is in German.

You can find the training of this 5-day MySQL/MariaDB training here.

If you have any question please do not hesitate to contact us.

Taxonomy upgrade extras: 

Short term notice: Percona XtraDB Cluster training in English 7/8 February 2018 in Germany

$
0
0

FromDual offers short term a Percona XtraDB Cluster and MySQL Galera Cluster training (2 days) in English.

The training will take place in the Linuxhotel in Essen/Germany on February 7/8 2018.

There are already enough registrations so it is certain the training will take place. But there are still free places for some additional participants.

You can book online at the Linuxhotel.

Important: The Linuxhotel is nearly fully booked out. So accommodation is in nearby locations. The Linuxhotel will recommend you some locations.

The training is in English.

You can find the contents of this 2-day Percona XtraDB Cluster training here.

If you have any question please do not hesitate to contact us.

MySQL 8.0.4-rc is out

$
0
0

Yesterday MySQL 8.0.4-rc came out. The Release Notes are quite long.
But caution: Do a BACKUP before upgrading...

I experienced some nice surprises. First I have to admit that I did not read the Release Notes or anything else. Reading manuals is for Girlies! Possibly something is written in there which is of importance. But I expect that it just works as usual...

I downloaded MySQL 8.0.4-rc and just want to upgrade my MySQL 8.0.3-rc testing system, where we did the 1M tables test.

First I got:

[MY-011096] No data dictionary version number found.
[MY-010020] Data Dictionary initialization failed.
[MY-010119] Aborting

Hmmm... Maybe something was not clean with the old system. So downgrade again:

[ERROR] [000000] InnoDB: Unsupported redo log format. The redo log was created with MySQL 8.0.4. Please follow the instructions at http://dev.mysql.com/doc/refman/8.0/en/upgrading-downgrading.html
[ERROR] [000000] InnoDB: Plugin initialization aborted with error Generic error
[ERROR] [003957] Failed to initialize DD Storage Engine
[ERROR] [003634] Data Dictionary initialization failed.
[ERROR] [003742] Aborting

OK. Understandable. I should have done a backup before. But backup is for Girlies as well! Anyway this test system is not important. So I created a new instance from scratch which finally worked... Possibly just removing the redo log files as indicated would have helped as well.

Advanced MySQL Enterprise Training by FromDual

$
0
0

Due to the increasing demand FromDual has developed an Advanced MySQL Enterprise Training for DBAs and DevOps. After testing this training extensively with some selected customers last year we offer this MySQL Enterprise Training in 2018 for a broader audience.

The MySQL Enterprise Training addresses MySQL DBAs and DevOps which are already familiar with MySQL and approach now the challenge to operate a serious MySQL Enterprise infrastructure.

The topics of the 3 days MySQL Enterprise training you can find here.

You further have the opportunity to add 2 extra days of MySQL Performance Tuning from the Advanced MySQL Training.

We would be pleased to hold this training in-house in your company or at the location of one of our training partners in Essen, Berlin and Cologne (Germany).

For any question please contact us by eMail.

Taxonomy upgrade extras: 

MySQL Environment MyEnv 2.0.0 has been released

$
0
0

FromDual has the pleasure to announce the release of the new version 2.0.0 of its popular MySQL, Galera Cluster and MariaDB multi-instance environment MyEnv.

The new MyEnv can be downloaded here. How to install MyEnv is described in the MyEnv Installation Guide.

In the inconceivable case that you find a bug in the MyEnv please report it to the FromDual bug tracker.

Any feedback, statements and testimonials are welcome as well! Please send them to feedback@fromdual.com.

Upgrade from 1.1.x to 2.0.0

MyEnv 2.0.0 requires an new PHP package for socket handling. On Red Hat, CentOS, Debian and Ubuntu it seems to be installed by default. On OpenSUSE it has to be installed (php-sockets). For more details see also our MyEnv Installation Guide.

shell> sudo zypper install php-sockets   # on OpenSUSE and SLES only

shell> cd ${HOME}/product
shell> tar xf /download/myenv-2.0.0.tar.gz
shell> rm -f myenv
shell> ln -s myenv-2.0.0 myenv

Plug-ins

If you are using plug-ins for showMyEnvStatus create all the links in the new directory structure:

shell> cd ${HOME}/product/myenv
shell> ln -s ../../utl/oem_agent.php plg/showMyEnvStatus/

Upgrade of the instance directory structure

From MyEnv v1 to v2 the directory structure of instances has fundamentally changed. Nevertheless MyEnv v2 works fine with MyEnv v1 directory structures.

Old structure

~/data/instance1/ibdata1
~/data/instance1/ib_logfile?
~/data/instance1/my.cnf
~/data/instance1/error.log
~/data/instance1/mysql
~/data/instance1/test~/data/mypprod/
~/data/instance1/general.log
~/data/instance1/slow.log
~/data/instance1/binlog.0000??
~/data/instance2/...

New structure

~/database/instance1/binlog/binlog.0000??
~/database/instance1/data/ibdata1
~/database/instance1/data/ib_logfile?
~/database/instance1/data/mysql
~/database/instance1/data/test
~/database/instance1/etc/my.cnf
~/database/instance1/log/error.log
~/database/instance1/log/general.log
~/database/instance1/log/slow.log
~/database/instance1/tmp/
~/database/instance2/...

But over time you possibly want to migrate the old structure to the new one. The following steps describe how you upgrade MyEnv instance structure v1 to v2:

mysql@chef:~ [mysql-57, 3320]> mypprod
mysql@chef:~ [mypprod, 3309]> stop
.. SUCCESS!
mysql@chef:~ [mypprod, 3309]> mkdir ~/database/mypprod
mysql@chef:~ [mypprod, 3309]> mkdir ~/database/mypprod/binlog ~/database/mypprod/data ~/database/mypprod/etc ~/database/mypprod/log ~/database/mypprod/tmp
mysql@chef:~ [mypprod, 3309]> mv ~/data/mypprod/binary-log.* ~/database/mypprod/binlog/
mysql@chef:~ [mypprod, 3309]> mv ~/data/mypprod/my.cnf ~/database/mypprod/etc/
mysql@chef:~ [mypprod, 3309]> mv ~/data/mypprod/error.log ~/database/mypprod/log/
mysql@chef:~ [mypprod, 3309]> mv ~/data/mypprod/slow.log ~/database/mypprod/log/
mysql@chef:~ [mypprod, 3309]> mv ~/data/mypprod/general.log ~/database/mypprod/log/
mysql@chef:~ [mypprod, 3309]> mv ~/data/mypprod/* ~/database/mypprod/data/
mysql@chef:~ [mypprod, 3309]> rmdir ~/data/mypprod
mysql@chef:~ [mypprod, 3309]> vi /etc/myenv/myenv.conf

- datadir              = /home/mysql/data/mypprod
+ datadir              = /home/mysql/database/mypprod/data
- my.cnf               = /home/mysql/data/mypprod/my.cnf
+ my.cnf               = /home/mysql/database/mypprod/etc/my.cnf
+ instancedir          = /home/mysql/database/mypprod

mysql@chef:~ [mypprod, 3309]> source ~/.bash_profile
mysql@chef:~ [mypprod, 3309]> cde
mysql@chef:~/database/mypprod/etc [mypprod, 3309]> vi my.cnf 

- log_bin                                = binary-log
+ log_bin                                = /home/mysql/database/mypprod/binlog/binary-log
- datadir                                = /home/mysql/data/mypprod
+ datadir                                = /home/mysql/database/mypprod/data
- tmpdir                                 = /tmp
+ tmpdir                                 = /home/mysql/database/mypprod/tmp
- log_error                              = error.log
+ log_error                              = /home/mysql/database/mypprod/log/error.log
- slow_query_log_file                    = slow.log
+ slow_query_log_file                    = /home/mysql/database/mypprod/log/slow.log
- general_log_file                       = general.log
+ general_log_file                       = /home/mysql/database/mypprod/log/general.log

mysql@chef:~/database/mypprod/etc [mypprod, 3309]> cdb
mysql@chef:~/database/mypprod/binlog [mypprod, 3309]> vi binary-log.index 

- ./binary-log.000001
+ /home/mysql/database/mypprod/binlog/binary-log.000001
- ./binary-log.000001
+ /home/mysql/database/mypprod/binlog/binary-log.000001

mysql@chef:~/database/mypprod/binlog [mypprod, 3309]> start
mysql@chef:~/database/mypprod/binlog [mypprod, 3309]> exit

Changes in MyEnv 2.0.0

MyEnv

  • New v2 instance directory structure and instancedir variable introduced, aliases adapted accordingly.
  • Configuration files aliases.conf and variables.conf made more user friendly.
  • PHP 7 support added.
  • Made MyEnv MySQL 8.0 ready.
  • Packaging (DEB/RPM) for RHEL 6 and 7 and SLES 11 and 12 DEB (Ubuntu/Debian) available.
  • OEM agent plug-in made ready for OEM v12.
  • More strict configuration checking.
  • Version more verbose.
  • Database health check mysqladmin replace by UNIX socket probing.
  • Various bug fixes (#168, #161, ...)
  • MyEnv made ready for systemd.
  • Bind-address output nicer in up.
  • New variables added to my.cnf template (super_read_only, innodb_tmpdir, innodb_flush_log_at_trx_commit, MySQL Group Replication, crash-safe Replication, GTID, MySQL 8.0)

MyEnv Installer

  • Installer made ready for systemd.
  • Question for angel process (mysqld_safe) and cgroups added.
  • Check for duplicate socket added.
  • Various bug fixes.
  • Purge data implemented.

MyEnv Utilities

  • Utility mysqlstat.php added.
  • Scripts for keepalived added.
  • Utilities mysql-create-instance.sh and mysql-remove-instance.sh removed.
  • Famous insert_test.sh, insert_test.php and test table improved.

For subscriptions of commercial use of MyEnv please get in contact with us.

Viewing all 292 articles
Browse latest View live