MariaDB cluster Version : mysql Ver 15.1 Distrib 10.0.24-MariaDB,
I have a two node + arbitrator cluster which is live and replicating data across nodes.
Unfortunately we found some inconsistency in some of the tables in Databases.
For instance:
Node1:
MariaDB [(none)]> select count(*) from example_db.reports;
+----------+
| count(*) |
+----------+
| 299 |
+----------+
1 row in set (0.00 sec)
Node2:
MariaDB [(none)]> select count(*) from example_db.reports;
+----------+
| count(*) |
+----------+
| 285 |
+----------+
1 row in set (0.00 sec)
Note: Not find any noticeable errors in mysql error log
What could be the reasons for these kind of inconsistency ?
Is that a bug or a known issues ?
Thank you.
I don't think there are any bugs in this very critical area.
In Galera clusters, you must check for errors after all statements, including COMMIT. (This is different than in ordinary replication.)
All tables are InnoDB, correct?
Related
I am at the REPEATABLE-READ level.
Why does it make me wait?
I understand that all reads (SELECTs) at any level are non-blocking.
what am I missing?
Session 1:
mysql> lock tables users write;
Query OK, 0 rows affected (0.00 sec)
Session 2:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from users where id = 1; // wait
Session 1:
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
Session 2:
mysql> select * from users where id = 1;
+----+-----------------+--------------------+------+---------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+------------+
| id | name | email | rol | email_verified_at | password | remember_token | created_at | updated_at | deleted_at |
+----+-----------------+--------------------+------+---------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+------------+
| 1 | Bella Lueilwitz | orlo19#example.com | NULL | 2022-08-01 17:22:29 | $2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi | MvMlaX9TQj | 2022-08-01 17:22:29 | 2022-08-01 17:22:29 | NULL |
+----+-----------------+--------------------+------+---------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+------------+
1 row in set (10.51 sec)
In this question the opposite is true
Why doesn't LOCK TABLES [table] WRITE prevent table reads?
You reference a question about MySQL 5.0 posted in 2013. The answer from that time suggests that the client was allowed to get a result that had been cached in the query cache. Since then, MySQL 5.6 and 5.7 disabled the query cache by default, and MySQL 8.0 removed the feature altogether. This is a good thing.
The documentation says:
WRITE lock:
Only the session that holds the lock can access the table. No other session can access it until the lock is released.
This was true in the MySQL 5.0 days too, but the query cache allowed some clients to get around it. But I guess it wasn't reliable even then, because if the client ran a query that happened not to be cached, I suppose it would revert to the documented behavior. Anyway, it's moot, because all currently supported versions of MySQL should have the query cache disabled or removed.
When I first started using MySQL, a select count(*) or select count(1) was almost instantaneous. But I'm now using version 5.6.25 hosted at Dreamhost, and it's taking 20-30 seconds, sometimes, to do a select count(1). However, the second time it's fast---like the index is cached---but not super fast, like the data are coming from just the metadata index.
Anybody understand what's going on, and why it has changed?
mysql> select count(1) from times;
+----------+
| count(1) |
+----------+
| 1511553 |
+----------+
1 row in set (22.04 sec)
mysql> select count(1) from times;
+----------+
| count(1) |
+----------+
| 1512007 |
+----------+
1 row in set (0.54 sec)
mysql> select version();
+------------+
| version() |
+------------+
| 5.6.25-log |
+------------+
1 row in set (0.00 sec)
mysql>
I guess when you first started, you used MyISAM, and now you are using InnoDB. InnoDB just doesn't store this information. See documentation: Limits on InnoDB Tables
InnoDB does not keep an internal count of rows in a table because concurrent transactions might “see” different numbers of rows at the same time. To process a SELECT COUNT(*) FROM t statement, InnoDB scans an index of the table, which takes some time if the index is not entirely in the buffer pool. To get a fast count, you have to use a counter table you create yourself and let your application update it according to the inserts and deletes it does. If an approximate row count is sufficient, SHOW TABLE STATUS can be used. See Section 9.5, “Optimizing for InnoDB Tables”.
So when your index is entirely in the buffer pool after the (slower) first query, the second query is fast again.
MyISAM doesn't need to care about problems that concurrent transactions might create, because it doesn't support transactions, and so select count(*) from t will just look up and return a stored value very fast.
How can I enable strict sql_mode in MySQL?
I want to fetch data from SQL and process the same in strict mode.
My current sql_mode is:
mysql> SELECT ##sql_mode;
+------------------------+
| ##sql_mode |
+------------------------+
| NO_ENGINE_SUBSTITUTION |
+------------------------+
You basically have two ways of doing it, using SQL command or changing configuration file. If you set it using SQL command - it will change back after the server is restarted.
Doing it in SQL:
SET GLOBAL sql_mode='STRICT_TRANS_TABLES';
Doing it in config file:
[mysqld]
sql_mode="STRICT_TRANS_TABLES"
File location varies depending on your operating system, more on where to find it here: https://dev.mysql.com/doc/refman/5.7/en/option-files.html
Important to note, that you can have multiple modes specified:
sql_mode="STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION"
this is especially important when using SQL statement, since it could override your whole mode string.
More stuff about SQL modes here: https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html
Do the following:
SET GLOBAL sql_mode='STRICT_TRANS_TABLES';
The other answers are correct, but they don't work (as-is) for AWS RDS.
If you are running a MySQL server on AWS RDS, then you can't run SET GLOBAL sql_mode='STRICT_TRANS_TABLES'; straightaway because you don't have the requisite permissions, even with admin-level credentials:
mysql> SET GLOBAL sql_mode='STRICT_ALL_TABLES';
ERROR 1227 (42000): Access denied; you need (at least one of) the SUPER or SYSTEM_VARIABLES_ADMIN privilege(s) for this operation
In AWS RDS, since it's a managed DB service, you don't have access to the my.cnf or other configuration files directly - so you can't change the settings there either.
However, note that you can set sql_mode at the session-level, but this will be lost across session changes or reboots:
mysql> SET SESSION sql_mode='STRICT_ALL_TABLES';
Query OK, 0 rows affected, 1 warning (0.30 sec)
mysql> SELECT ##session.sql_mode;
+---------------------+
| ##session.sql_mode |
+---------------------+
| STRICT_ALL_TABLES |
+---------------------+
1 row in set (0.31 sec)
So then how do you change sql_mode (or any other parameters for that matter) at a GLOBAL level so that they persist across restarts in AWS RDS MySQL?
You need to create a custom DB Parameter Group in RDS (for example, using the web console) like this:
Then you have to modify your RDS instance and apply the newly-created Parameter Group like so:
Finally, apply your modifications, and reboot (yes, reboot is required) the instance.
And voila, you have your sql_mode set as needed, and it persists across reboots now:
mysql> SELECT ##sql_mode;
+------------------------------------------+
| ##sql_mode |
+------------------------------------------+
| STRICT_ALL_TABLES,NO_ENGINE_SUBSTITUTION |
+------------------------------------------+
1 row in set (0.69 sec)
mysql> SELECT ##global.sql_mode;
+------------------------------------------+
| ##global.sql_mode |
+------------------------------------------+
| STRICT_ALL_TABLES,NO_ENGINE_SUBSTITUTION |
+------------------------------------------+
1 row in set (0.62 sec)
mysql> SELECT ##session.sql_mode;
+------------------------------------------+
| ##session.sql_mode |
+------------------------------------------+
| STRICT_ALL_TABLES,NO_ENGINE_SUBSTITUTION |
+------------------------------------------+
1 row in set (0.38 sec)
I tried to test if a line is met in some distance from a point. St_distance just gives me what I want. However, I'm curious about st_intersects + st_buffer:
$ mysql --version
mysql Ver 14.14 Distrib 5.6.24, for Linux (x86_64) using EditLine wrapper
mysql> set #l4=st_geomfromtext('LINESTRING(50 50, 52 45)');
mysql> set #g4=st_geomfromtext('POINT(50 49)');
mysql> select st_distance(#l4, #g4);
--------------
select st_distance(#l4, #g4)
--------------
+-----------------------+
| st_distance(#l4, #g4) |
+-----------------------+
| 0.3713906763541037 |
+-----------------------+
1 row in set (0.00 sec)
I would think the point is very close to the line but obviously MySQL disagrees:
mysql> select st_intersects(st_buffer(#g4, 1), #l4);
--------------
select st_intersects(st_buffer(#g4, 1), #l4)
--------------
+---------------------------------------+
| st_intersects(st_buffer(#g4, 1), #l4) |
+---------------------------------------+
| 0 |
+---------------------------------------+
1 row in set (0.00 sec)
Why? Do I miss something?
P.S.
I have tried the commands above in H2GIS and it says it is indeed true!
ST_Intersects should return true in this case.
This appears to be the bug reported here: https://bugs.mysql.com/bug.php?id=71076, and fixed in MySQL 5.7.6, according to the release notes here: http://forums.mysql.com/read.php?3,629183,629183
"This work also corrected issues that [...], and that
ST_Intersects() sometimes incorrectly calculated the
result for intersections of LineString and Polygon."
I've been passing through this problem for one day, and it's hard to understand why MySql doesn't work easily.
I'm trying to execute the statement below, but it isn't recognized at all.
SELECT TO_SECONDS('2013-09-12 11:15:00');
I get the following error:
ERROR 1305 (42000): FUNCTION db.to_seconds does not exist
I've checked MySQL's documentation and this function is available since version 5.5. So, I updated my previous version and now I'm working with 6.0 (Server version: 6.0.4-alpha-community-log MySQL Community Server (GPL)) but still not working.
mysql> select version();
+---------------------------+
| version() |
+---------------------------+
| 6.0.4-alpha-community-log |
+---------------------------+
1 row in set (0.03 sec)
Anyone knows what is going on?
TO_SECONDS('2013-09-12 11:15:00');
Seconds are a measure of time interval not a time datum - this therefore implies some sort of reference datum - but when there's lots to choose from, which do you want? One solution is to define your own datum:
SELECT TIME_DIFF('2013-09-12 11:15:00', '01-01-2000 00:00:00')
Or use the Unix epoch:
SELECT UNIX_TIMESTAMP('2013-09-12 11:15:00')
I was using MySQL version 6.0 that was installed by AppServ (Apache, MySQL, PHP, phpmyadmin) tool and this version of MySQL hasn't support for TO_SECONDS function. After installing MySQL 5.5 it's working perfectly.
mysql> select to_seconds('2013-09-02 13:33:59');
+-----------------------------------+
| to_seconds('2013-09-02 13:33:59') |
+-----------------------------------+
| 63545348039 |
+-----------------------------------+
1 row in set (0.00 sec)