[MDEV-25598] INNODB_ROWS_UPDATED / n_rows_updated can become imprecise under heavy load Created: 2021-05-05 Updated: 2021-05-21 |
|
| Status: | Open |
| Project: | MariaDB Server |
| Component/s: | Storage Engine - InnoDB |
| Affects Version/s: | 10.5.9 |
| Fix Version/s: | 10.5 |
| Type: | Bug | Priority: | Major |
| Reporter: | Lau | Assignee: | Marko Mäkelä |
| Resolution: | Unresolved | Votes: | 1 |
| Labels: | innodb | ||
| Environment: |
Any |
||
| Description |
|
(We are currently in the process of adding Pomelo.EntityFramework.MySql and related benchmarks to the TechEmpower Framework Benchmarks. As part of that, I have also prepared a PR that will add MariaDB as a database to the benchmark. Preliminary locally run tests show about a 4 % increase in speed over MySQL. Feel free to join the conversation.) Affects all versions of MariaDB and MySQL. Issue:The INNODB_ROWS_UPDATED status variable is used by the TechEmpower Framework Benchmarks for MariaDB (and MySQL) verifying the expected UPDATE count after a benchmark run. The framework tests different scenarios from little to high loads (high concurrency). When running 10240 updates, divided into 512 concurrent calls, so 20 updates per connection, MariaDB (and MySQL) regularly only reports between 10237 and 10239 updates, even though all 10240 updates where successfully executed. It seems, that the srv_stats.n_rows_updated.inc(); calls increment the stats in an concurrency unsafe way:
The current workaround is to heuristically ignore the difference, if it is within an expected margin, which defeats the purpose of verifying the accuracy/health of the benchmark before running it. How to repeat:Run 10240 updates, divided in 512 (truly) concurrent connections, against any MariaDB (or MySQL) InnoDB table and check the expected INNODB_ROWS_UPDATED (and INNODB_ROWS_READ) count against the actual one. They should differ in about 4 out of 5 runs. Suggested fix:I would propose to use interlocked increment operations for inc() and interlocked add operations for add(), for a maximum in performance and counting accuracy at the same time. |
| Comments |
| Comment by Lau [ 2021-05-08 ] | ||||
|
The following post was added to the bug report on the MySQL issue tracker in response to the bug that I reported there:
I posted the following response to it:
| ||||
| Comment by Sergei Golubchik [ 2021-05-13 ] | ||||
|
marko, what do you think? | ||||
| Comment by Lau [ 2021-05-21 ] | ||||
|
Here is a locally run benchmark (using a proven benchmark library) that measures the time of 100 simple increments against 100 interlocked increments:
So a simple increment instruction takes about 1.167 ns on my local machine (single CPU, 8 cores), while an interlocked increment takes about 5 times that amount with 5.259 ns. Assuming around 1,000 UPDATE statements within one second (which already requires beefy hardware for MySQL, according to the TechEmpower Framework Benchmark), the 5.259 ns would take up about 0.0005259 % of the time spend for a request. In total, it would add 5 additional microseconds for 1,000 UPDATE statements per second (1.000005 seconds instead of 1 second). |