Feb
28
2014
--

How to avoid common (but deadly) MySQL development mistakes

How to avoid common (but deadly) MySQL development mistakes: WebinarMySQL software developers are under pressure to do more in less time and create applications that adapt to ever-changing requirements. And it’s true that some of a developer’s time is wasted when his or her method of optimizing involves trying every combination of code and index definition.

There is a better way. And next Wednesday at 10 a.m. Pacific time, I’ll show you how. In my webinar, “How to Avoid Common (but Deadly) MySQL Development Mistakes,” you’ll lean:

  • How to find out which indexes are the best fit for your MySQL application
  • How to protect yourself from the number one MySQL database security vulnerability on the web
  • How to decide when to optimize a MySQL database application with denormalization, indexes, caching, partitioning, sharding

You’ll step away from your computer afterward being more confident and ultimately more productive as you develop MySQL database-driven applications. Register now to reserve your spot (it’s free). The same link will give you access to the recording later.

The post How to avoid common (but deadly) MySQL development mistakes appeared first on MySQL Performance Blog.

Feb
28
2014
--

How rows_sent can be more than rows_examined?

When looking at queries that are candidates for optimization I often recommend that people look at rows_sent and rows_examined values as available in the slow query log (as well as some other places). If rows_examined is by far larger than rows_sent, say 100 larger, then the query is a great candidate for optimization. Optimization could be as simple as adding a few indexes or much more complicated as in generating summary tables so you do not need to rely on large aggregations for your real-time queries.

Just to be clear this is a great rule for your “real time” queries need to be handled very quickly and in high volumes. Batch jobs, reporting queries often will have to scan through millions of rows to get few rows of result set and it is fine.

So it is all clear with rows_sent being smaller than rows_examined but can it be smaller ? Yes it can! Here are couple of things you need to be aware in this regard:

Query served without Execution
As strange as this might sound it is very much possible in MySQL. Some queries can be completely resolved during the “optimization” stage so there is no need to really execute a query by accessing the tables. You will see “Select tables optimized away” in the query EXPLAIN in this case:

explain select count(comment_count) from wp_posts;
+----+-------------+---------------------------+-----------------------------+
| id | select_type | table,type,possible_keys, | Extra                       |
|    |             | key,key_len,ref,rows      |                             |
+----+-------------+---------------------------+-----------------------------+
| 1  | SIMPLE      | all NULLs                 | Select tables optimized away|
+----+-------------+---------------------------+-----------------------------+
1 row in set (0.00 sec)

Typically you will see this when having count(*) with MyISAM tables as in the example above as well as using MIN/MAX aggregate functions on the indexed column.

Reading data from the Index
Observing such behavior I’ve seen people thinking it could be due to using “Covering Index.” MySQL is reading data from the index in this case, not rows, right? Wrong! For the sake of counting this variable MySQL does not make a difference whenever it could read the data from the index alone or “data” had to be consulted. In both cases it will be seen as row which has been examined.

Index Condition Pushdown
Index Condition Pushdown really breaks things here as when index entries are filtered on storage engine level they are not counted towards row_examined, at least in MySQL 5.6. This is unfortunate as it may make queries using Index Condition Pushdown to look less expensive than they actually are. In some cases possibly 100x or more less expensive when a Index Condition Pushdown is used to filter out large portion of the rows. I wish storage engine could track how many rows it examines through Index Condition Pushdown and how many it filters out so rows_examined could account it properly.

Query Cache
Query Cache is another interesting case as any query cache hit will have rows_examined and rows_sent being zero. It might be confusing at first – one could expect the rows_examined be zero as no tables are being read while rows_sent have an actual number because result set is sent to the client. What happens in reality is – Query Cache caches the result set packets as they are sent to the client and they are sent again on query cache hit without any parsing so server does not know how many rows are being sent. I wish number of rows sent would be stored together with query result and as such be available in the log files, though I do not expect it ever fixed as Query Cache is something which is not getting a lot of attention this way.

Summary
Well… you can get rows_examined less than rows_sent but I only expect to see it for some rare kind of queries. There are also different cases you need to be aware of which may cause rows_sent or rows_examined not to be represented of the actual processing query requires or size of actual result sets.

The post How rows_sent can be more than rows_examined? appeared first on MySQL Performance Blog.

Feb
27
2014
--

DBA 101: Sometimes forgotten functionality in the MySQL client

The MySQL client has some functionalities some of us never use. Why would you use them and what is the added value of this?

Every DBA and developer has had a moment when he or she needs to connect to a MySQL database using the command line tool. Therefore I’ve written down an explanation of some command line commands you can insert in the CLI, most of them give added value and make your experience with the cli more enjoyable.

prompt

Who has never witnessed the scary feeling of not being connected to the write database when having several terminals open. I do, due to the fact I use the prompt functionality.

mysql >\R Production >
PROMPT set to 'Production > '

Or you can go a bit further and visualise the user, host and active database in:

mysql > \R \u@\h [\d]>
PROMPT set to '\u@\h [\d]>'
root@testbox [test]>

edit

In some situations editing the query in an editor instead of the cli can have several enhancements. It gives you the ability to fix typos, have a deep look at the queries before you submit them and etc.
If you’d like to edit the query you are making in your default editor instead of using the cli.

mysql> \e

The editor appears, in which you can create your query/ies.

use sakila;
select * from city
limit 10;
~
~
~

After closing this down and putting a delimiter in the cli, this query will be run against the database while outputting in the prompt.

mysql> \e
-> ;
+---------+--------------------+------------+---------------------+
| city_id | city               | country_id | last_update         |
+---------+--------------------+------------+---------------------+
|       1 | A Corua (La Corua) |         87 | 2006-02-15 04:45:25 |
|       2 | Abha               |         82 | 2006-02-15 04:45:25 |
|       3 | Abu Dhabi          |        101 | 2006-02-15 04:45:25 |
|       4 | Acua               |         60 | 2006-02-15 04:45:25 |
|       5 | Adana              |         97 | 2006-02-15 04:45:25 |
|       6 | Addis Abeba        |         31 | 2006-02-15 04:45:25 |
|       7 | Aden               |        107 | 2006-02-15 04:45:25 |
|       8 | Adoni              |         44 | 2006-02-15 04:45:25 |
|       9 | Ahmadnagar         |         44 | 2006-02-15 04:45:25 |
|      10 | Akishima           |         50 | 2006-02-15 04:45:25 |
+---------+--------------------+------------+---------------------+
10 rows in set (0.03 sec)

tee

Performing critical maintenance on a database could require to have an entire log of performed queries and actions. You can activate the full output of the MySQL client, including your performed queries. This utility is ideal if you prefer having a log of all of your actions. This could be for documentation stakes or a way to reread your actions if issues would occur.

Example:

mysql> \T /tmp/tee.log
Logging to file '/tmp/tee.log'

This will provide in the output the queries you perform.

dim0@testing101:~$ cat /tmp/tee.log
mysql> select * from city limit 5;
+---------+--------------------+------------+---------------------+
| city_id | city               | country_id | last_update         |
+---------+--------------------+------------+---------------------+
|       1 | A Corua (La Corua) |         87 | 2006-02-15 04:45:25 |
|       2 | Abha               |         82 | 2006-02-15 04:45:25 |
|       3 | Abu Dhabi          |        101 | 2006-02-15 04:45:25 |
|       4 | Acua               |         60 | 2006-02-15 04:45:25 |
|       5 | Adana              |         97 | 2006-02-15 04:45:25 |
+---------+--------------------+------------+---------------------+
5 rows in set (0.00 sec)

Whenever, you have only access to the MySQL interface and you need to access one of your created files to see what the output is, you can do so using the \! keystroke, which will execute system commands.
Running a shell command from the MySQL command line interface:

mysql> \! cat /tmp/tee.log
mysql> select * from city limit 5;
+---------+--------------------+------------+---------------------+
| city_id | city               | country_id | last_update         |
+---------+--------------------+------------+---------------------+
|       1 | A Corua (La Corua) |         87 | 2006-02-15 04:45:25 |
|       2 | Abha               |         82 | 2006-02-15 04:45:25 |
|       3 | Abu Dhabi          |        101 | 2006-02-15 04:45:25 |
|       4 | Acua               |         60 | 2006-02-15 04:45:25 |
|       5 | Adana              |         97 | 2006-02-15 04:45:25 |
+---------+--------------------+------------+---------------------+
5 rows in set (0.00 sec)

status

In some cases you’d like seeing the parameters currently active on your MySQL client. Therefore you can actually use the \s command. This command will clarify which of the options are active on the client. The info which is shown should not be confused with SHOW VARIABLES. which is focussed on the connection variables.
Trigger the status information of your connection using \s:

mysql> \s>
--------------
mysql  Ver 14.14 Distrib 5.6.15, for Linux (x86_64) using  EditLine wrapper
Connection id:		13149
Current database:	sakila
Current user:		root@localhost
SSL:			Not in use
Current pager:		stdout
Using outfile:		''
Using delimiter:	;
Server version:		5.6.15-63.0-log Percona Server (GPL), Release 63.0
Protocol version:	10
Connection:		127.0.0.1 via TCP/IP
Server characterset:	latin1
Db     characterset:	latin1
Client characterset:	utf8
Conn.  characterset:	utf8
TCP port:		3306
Uptime:			10 days 23 hours 32 min 57 sec
Threads: 1  Questions: 1203169  Slow queries: 43745  Opens: 626  Flush tables: 1  Open tables: 178  Queries per second avg: 1.268
--------------

clear

Clearing your current input query. Use \c to clear the input field:

mysql> SELECT *
-> FROM city
-> \c
mysql>

pager

Honestly one of the more useful tools in the mysqlclient is actually pager. For people prone to typing queries while forgetting adding a limit if they don’t need to view the full output.
‘\P less’ will output the query data using the UNIX command less.
You can also choose to output the query results in a parsable format on the filesystem using ‘\P cat > voila.log’.

for example:

mysql> \P cat > /tmp/voila.log
PAGER set to 'cat > /tmp/voila.log'
mysql> SELECT *  FROM city;
600 rows in set (0.01 sec)

This will create the file ‘voila.log’ in which only the output is saved of the query. This solution mimics the ‘SELECT INTO OUTFILE’ query.

During optimisation of your workload, it can be interesting to see if a query you’ve modified has the same query output

mysql >\P md5sum
PAGER set to 'md5sum'
 root@127.0.0.1 [sakila]>select * from city limit 10;
449d5bcae6e0e5b19e7101478934a7e6  -
10 rows in set (0.00 sec)
 mysql >select city_id, city, country_id, last_update FROM city LIMIT 10 ;
449d5bcae6e0e5b19e7101478934a7e6  -
10 rows in set (0.00 sec)

Other commands

There are of course several other options you might use. You can get an overview of all the internal cli functions through \?.

Disabling the tee and pager commands described in this blogentry can be done with \t or notee, \n or \nopager.

The post DBA 101: Sometimes forgotten functionality in the MySQL client appeared first on MySQL Performance Blog.

Feb
26
2014
--

Talking Drupal #038 – Talking with Dries

Show Topic

  • How Drupal got started
  • Some key moments for Drupal
  • Open source and core developers
  • Drupal 8
  • Acquia Lift

Module of the Week

  • Project Module – https://drupal.org/project/project

Links

  • Dries’s Blog – http://www.buytaert.net
  • Acquia – https://www.acquia.com

Hosts

  • Stephen Cross – www.ParallaxInfoTech.com @stephencross
  • John Picozzi – www.RubicDesign.com @johnpicozzi 
  • Nic Laflin – www.nLightened.net @nicxvan
  • Jason Pamental – www.hwdesignco.com @jpamental
  • Dries Buytaert – buytaert.net @dries

 

Feb
26
2014
--

Talking Drupal #038 – Talking with Dries

Show Topic

  • How Drupal got started
  • Some key moments for Drupal
  • Open source and core developers
  • Drupal 8
  • Acquia Lift

Module of the Week

  • Project Module – https://drupal.org/project/project

Links

  • Dries’s Blog – http://www.buytaert.net
  • Acquia – https://www.acquia.com

Hosts

  • Stephen Cross – www.ParallaxInfoTech.com @stephencross
  • John Picozzi – www.RubicDesign.com @johnpicozzi 
  • Nic Laflin – www.nLightened.net @nicxvan
  • Jason Pamental – www.hwdesignco.com @jpamental
  • Dries Buytaert – buytaert.net @dries

 

Feb
26
2014
--

How to monitor ALTER TABLE progress in MySQL

While working on a recent support issue as a Percona Support Engineer,  I got one question from a customer asking how to monitor ALTER TABLE progress. Actually, for MySQL 5.5 and prior versions, it’s quite difficult to ALTER the table in a running production environment especially for large tables (with millions records). Because it will rebuild and lock the table affecting the performance as well as our users. Therefore even if we start ALTER it’s really important to know when it will finish. Even while creating the index, ALTER TABLE will not rebuild the table if fast_index_creation is ON but still it might lock the table.

fast_index_creation feature was introduced in MySQL 5.5 and higher versions. Also available in MySQL 5.1 with the InnoDB Plugin

From MySQL 5.6 and later, “Online DDL” feature has been introduced, which is enhancing many other types of ALTER TABLE operations to avoid “copying the table” and “locking.” It  also allows SELECT, INSERT, UPDATE, and DELETE statements to run while the table is being altered. So in latest version, we can control the copy of file and locking by using ALGORITHM and LOCK options. But even in MySQL 5.6, there are some ALTER operations which still required table rebuild i.e ADD/DROP column, change data type, ADD/DROP primary key etc. You can check table here for more details.

Summary of Online Status for DDL Operations”  http://dev.mysql.com/doc/refman/5.6/en/innodb-create-index-overview.html

So in any case, if required, we can check the ALTER TABLE progress with below solutions. 

One of the solutions is to use the Percona Toolkit utility, pt-online-schema-change which will ALTER the table without locking it for long time and show the progress. i.e

nilnandan@Dell-XPS:~$ pt-online-schema-change --alter "ADD COLUMN phone INT" u=root,p=root,D=nil,t=nil_test --execute
No slaves found. See --recursion-method if host Dell-XPS has slaves.
Not checking slave lag because no slaves were found and --check-slave-lag was not specified.
Operation, tries, wait:
copy_rows, 10, 0.25
create_triggers, 10, 1
drop_triggers, 10, 1
swap_tables, 10, 1
update_foreign_keys, 10, 1
Altering `nil`.`nil_test`...
Creating new table...
Created new table nil._nil_test_new OK.
Altering new table...
Altered `nil`.`_nil_test_new` OK.
2014-02-07T12:20:54 Creating triggers...
2014-02-07T12:20:54 Created triggers OK.
2014-02-07T12:20:54 Copying approximately 12583349 rows...
Copying `nil`.`nil_test`: 29% 01:12 remain
Copying `nil`.`nil_test`: 60% 00:38 remain
Copying `nil`.`nil_test`: 91% 00:08 remain
2014-02-07T12:22:33 Copied rows OK.
2014-02-07T12:22:33 Swapping tables...
2014-02-07T12:22:33 Swapped original and new tables OK.
2014-02-07T12:22:33 Dropping old table...
2014-02-07T12:22:33 Dropped old table `nil`.`_nil_test_old` OK.
2014-02-07T12:22:33 Dropping triggers...
2014-02-07T12:22:33 Dropped triggers OK.
Successfully altered `nil`.`nil_test`.
nilnandan@Dell-XPS:~$

While using pt-online-schema-change, many times I get questions such as: “What will happen to those data changes (INSERT/UPDATE/DELETE) which are performing during the ALTER TABLE?”

Here, I would like to explain briefly about it. While running pt-online-schema-change, if we will check data dir,

root@Dell-XPS:/var/lib/mysql/nil# ll
total 830524
drwx------ 2 mysql mysql 4096 Feb 7 12:20 ./
drwxr-xr-x 5 mysql mysql 4096 Feb 7 12:05 ../
-rw-rw---- 1 mysql mysql 65 Jan 31 12:12 db.opt
-rw-rw---- 1 mysql mysql 8616 Feb 7 12:06 nil_test.frm
-rw-rw---- 1 mysql mysql 822083584 Feb 7 12:18 nil_test.ibd
-rw-rw---- 1 mysql mysql 8648 Feb 7 12:20 _nil_test_new.frm
-rw-rw---- 1 mysql mysql 28311552 Feb 7 12:20 _nil_test_new.ibd
-rw-rw---- 1 mysql mysql 944 Feb 7 12:20 nil_test.TRG
-rw-rw---- 1 mysql mysql 40 Feb 7 12:20 pt_osc_nil_nil_test_del.TRN
-rw-rw---- 1 mysql mysql 40 Feb 7 12:20 pt_osc_nil_nil_test_ins.TRN
-rw-rw---- 1 mysql mysql 40 Feb 7 12:20 pt_osc_nil_nil_test_upd.TRN

We can see that it will create triggers (separate trigger for INSERT, UPDATE and DELETE) on the original table to update corresponding rows to the new table( _nil_test_new). So any modifications happened to the data in original tables during the copy, will be reflected in the new table.

NOTE: This tool will not work if any triggers are already defined on the table.

But what if we don’t want to use pt-online-schema-change and run regular ALTER TABLE on mysql prompt? After some research I found many ways to calculate the progress of ALTER TABLE specially with innodb_file_per_table is ON. (innodb_file_per_table is ON by default in MySQL 5.6.)

  • Calculate the progress by checking the size of temporary tablespace. 

With innodb_file_per_table=1,when we are running ALTER TABLE, innodb creates a temporary tablespace within the same data directory with random name starting from #sql ending with .ibd like #sql-1c80_27.ibd. i.e

root@Dell-XPS:/var/lib/mysql/nil# ll                    
...
-rw-rw---- 1 mysql mysql 8682 Feb 7 13:33 nil_test.frm
-rw-rw---- 1 mysql mysql 335544320 Feb 7 13:34 nil_test.ibd
-rw-rw---- 1 mysql mysql 8716 Feb 7 13:35 #sql-1c80_27.frm
-rw-rw---- 1 mysql mysql 23068672 Feb 7 13:35 #sql-1c80_27.ibd

While altering table, innodb reads original ibd file like nil_test.ibd and writes new pages to #sql-1c80_27.ibd. So with file size of nil_test.ibd and temporary #sql-1c80_27.ibd , we can check the ALTER TABLE progress with something like, 

#!/bin/bash
while true
do
A=`du -m '#sql'*'.ibd' 2>/dev/null|cut -f 1`;
# if $A -lt 0 ;
if [[ -z "$A" ]] ;
then
echo "Done";
exit 0 ;
fi
TABLENAME='nil_test';
TT=$TABLENAME.ibd;
B=`du -m $TT |cut -f 1`;
echo "ALTER TABLE $TABLENAME...$A MB written to tmp tablespace out of $B MB";
sleep 10
done

When we run ALTER on mysql, we can simply run this script in data dir and check the progress like,

mysql> ALTER TABLE nil_test ADD COLUMN phone int;
Query OK, 7582912 rows affected (58.54 sec)
Records: 7582912 Duplicates: 0 Warnings: 0
root@Dell-XPS:/var/lib/mysql/nil# ./alter_table_monitor.sh
ALTER TABLE nil_test...23 MB written in tmp file out of 485 MB
ALTER TABLE nil_test...73 MB written in tmp file out of 485 MB
ALTER TABLE nil_test...121 MB written in tmp file out of 485 MB
ALTER TABLE nil_test...173 MB written in tmp file out of 485 MB
ALTER TABLE nil_test...225 MB written in tmp file out of 485 MB
ALTER TABLE nil_test...277 MB written in tmp file out of 485 MB
ALTER TABLE nil_test...333 MB written in tmp file out of 485 MB
ALTER TABLE nil_test...381 MB written in tmp file out of 485 MB
ALTER TABLE nil_test...433 MB written in tmp file out of 485 MB
ALTER TABLE nil_test...481 MB written in tmp file out of 485 MB
Done
root@Dell-XPS:/var/lib/mysql/nil#

There are couple of things which we need to consider while using this script.

  1. We have to change script with $TABLENAME as per your requirement. It will work for only one ALTER TABLE.
  2. Script should run from database dir (i.e /var/lib/mysql/nil)
  3. This calculations are an approximation, because new table can be a bit different in size. For example, deleted rows or fragmentation can cause accuracy problems. 

I would like to mention here that we cannot check the progress of every ALTER TABLE with the above formula. For example, with fast_index_creation, It will create the table without any secondary indexes, then adding the secondary indexes after the data is loaded so it will not create temp tablespace (.ibd file) while creating secondary index. This process is very interesting, let me explain here.

When we add secondary index with ‘fast_index_creation‘, it will only create #sql***.frm file to update table structure but not temporary .ibd file. It will do some file sorts and then add directly index to original table.ibd file. so when you monitors those files, initially you didn’t see that file size increasing, but after some time (after files sorts) file size starts increasing till the end of ALTER TABLE. i.e

Initially, you’ll see

root@Dell-XPS:/var/lib/mysql/nil# ll
total 409644
drwx------ 2 mysql mysql 4096 Feb 12 10:50 ./
drwxr-xr-x 5 mysql mysql 4096 Feb 12 10:10 ../
-rwxr-xr-x 1 root root 306 Feb 7 13:35 alter_table_monitor.sh*
-rw-rw---- 1 mysql mysql 65 Jan 31 12:12 db.opt
-rw-rw---- 1 mysql mysql 8750 Feb 12 10:26 nil_test.frm
-rw-rw---- 1 mysql mysql 419430400 Feb 12 10:50 nil_test.ibd
-rw-rw---- 1 mysql mysql 8750 Feb 12 10:50 #sql-671_25.frm
...
root@Dell-XPS:/var/lib/mysql/nil# ll
total 409644
drwx------ 2 mysql mysql 4096 Feb 12 10:50 ./
drwxr-xr-x 5 mysql mysql 4096 Feb 12 10:10 ../
-rwxr-xr-x 1 root root 306 Feb 7 13:35 alter_table_monitor.sh*
-rw-rw---- 1 mysql mysql 65 Jan 31 12:12 db.opt
-rw-rw---- 1 mysql mysql 8750 Feb 12 10:26 nil_test.frm
-rw-rw---- 1 mysql mysql 419430400 Feb 12 10:50 nil_test.ibd
-rw-rw---- 1 mysql mysql 8750 Feb 12 10:50 #sql-671_25.frm

Then suddenly .ibd file size starts increasing…till end.

root@Dell-XPS:/var/lib/mysql/nil# ll
total 417836
drwx------ 2 mysql mysql 4096 Feb 12 10:50 ./
drwxr-xr-x 5 mysql mysql 4096 Feb 12 10:10 ../
-rwxr-xr-x 1 root root 306 Feb 7 13:35 alter_table_monitor.sh*
-rw-rw---- 1 mysql mysql 65 Jan 31 12:12 db.opt
-rw-rw---- 1 mysql mysql 8750 Feb 12 10:26 nil_test.frm
-rw-rw---- 1 mysql mysql 427819008 Feb 12 10:50 nil_test.ibd
-rw-rw---- 1 mysql mysql 8750 Feb 12 10:50 #sql-671_25.frm
....
root@Dell-XPS:/var/lib/mysql/nil# ll
total 487456
drwx------ 2 mysql mysql 4096 Feb 12 10:51 ./
drwxr-xr-x 5 mysql mysql 4096 Feb 12 10:10 ../
-rwxr-xr-x 1 root root 306 Feb 7 13:35 alter_table_monitor.sh*
-rw-rw---- 1 mysql mysql 65 Jan 31 12:12 db.opt
-rw-rw---- 1 mysql mysql 8750 Feb 12 10:50 nil_test.frm
-rw-rw---- 1 mysql mysql 499122176 Feb 12 10:51 nil_test.ibd
root@Nil-Dell-XPS:/var/lib/mysql/nil#

This will happen if there is only one secondary index. If there are multiple secondary indexes then for each index, process will pause, do file sorts and then add index so the number of pauses in file size increases, will be equal to number of secondary indexes.

  • Calculate the progress by checking the records in information_schema.GLOBAL_TEMPORARY_TABLES 

When the ALTER TABLE is running, we can also check GLOBAL_TEMPORARY_TABLES in information_schema and it will give you records count which are inserted in temporary table. i.e

mysql> select * from GLOBAL_TEMPORARY_TABLES \G;
*************************** 1. row ***************************
SESSION_ID: 38
TABLE_SCHEMA: nil
TABLE_NAME: #sql-1c80_27
ENGINE: InnoDB
NAME: #sql-696_26
TABLE_ROWS: 623711
AVG_ROW_LENGTH: 42
DATA_LENGTH: 26787840
INDEX_LENGTH: 0
CREATE_TIME: 2014-02-11 10:37:34
UPDATE_TIME: NULL
1 row in set (0.00 sec)
.......
mysql> select * from GLOBAL_TEMPORARY_TABLES \G;
*************************** 1. row ***************************
SESSION_ID: 38
TABLE_SCHEMA: nil
TABLE_NAME: #sql-1c80_27
ENGINE: InnoDB
NAME: #sql-696_26
TABLE_ROWS: 7017408
AVG_ROW_LENGTH: 42
DATA_LENGTH: 299663360
INDEX_LENGTH: 0
CREATE_TIME: 2014-02-11 10:37:34
UPDATE_TIME: NULL
1 row in set (0.01 sec)

  •  Calculate the progress by checking the Handler_read_rnd_next status variable (global counters).  

While running ALTER TABLE, we can also check the handler_read_rnd_next status variable by “SHOW GLOBAL STATUS LIKE ‘Handler_read_rnd%’ OR mysqladmin extended. Check this 2008 post titled “How to estimate query completion time in MySQL” by Baron Schwartz. He describes it very well.

NOTE: This won’t need innodb_file_per_table = ON  but we can use this option only when there are no other parallel transactions running.

So normally in any case, it will become really difficult to find the ALTER TABLE progress unless MySQL itself will provide some feature like MariaDB is providing progress in “SHOW PROCESSLIST”  https://mariadb.com/kb/en/show-processlist/

I’ve installed MariaDB 5.5 locally and tried to check, along with “SHOW PROCESSLIST”, you can also check progress by running query against information_schema.processlist table. But I observed that progress time is different in both the output.  It looks like information_schema.processlist table gives accurate progress for ALTER TABLE.

[root@percona-pxc3 nil]# mysql -uroot -proot -e "select ID, USER, HOST, DB, TIME, STATE, INFO, STAGE, MAX_STAGE, PROGRESS from information_schema.processlist where ID = 2; show processlist"
+----+------+-----------+------+------+-------------------+--------------------------------------------+-------+-----------+----------+
| ID | USER | HOST | DB | TIME | STATE | INFO | STAGE | MAX_STAGE | PROGRESS |
+----+------+-----------+------+------+-------------------+--------------------------------------------+-------+-----------+----------+
| 2 | root | localhost | nil | 3 | copy to tmp table | ALTER TABLE nil_test ADD COLUMN phone1 int | 1 | 2 | 4.279 |
+----+------+-----------+------+------+-------------------+--------------------------------------------+-------+-----------+----------+
+----+------+-----------+------+---------+------+-------------------+--------------------------------------------+----------+
| Id | User | Host | db | Command | Time | State | Info | Progress |
+----+------+-----------+------+---------+------+-------------------+--------------------------------------------+----------+
| 2 | root | localhost | nil | Query | 3 | copy to tmp table | ALTER TABLE nil_test ADD COLUMN phone1 int | 2.140 |
| 29 | root | localhost | NULL | Query | 0 | NULL | show processlist | 0.000 |
+----+------+-----------+------+---------+------+-------------------+--------------------------------------------+----------+
[root@percona-pxc3 nil]#
...............
...........
[root@percona-pxc3 nil]# mysql -uroot -proot -e "select ID, USER, HOST, DB, TIME, STATE, INFO, STAGE, MAX_STAGE, PROGRESS from information_schema.processlist where ID = 2; show processlist"
+----+------+-----------+------+------+-------------------+--------------------------------------------+-------+-----------+----------+
| ID | USER | HOST | DB | TIME | STATE | INFO | STAGE | MAX_STAGE | PROGRESS |
+----+------+-----------+------+------+-------------------+--------------------------------------------+-------+-----------+----------+
| 2 | root | localhost | nil | 25 | copy to tmp table | ALTER TABLE nil_test ADD COLUMN phone1 int | 1 | 2 | 45.613 |
+----+------+-----------+------+------+-------------------+--------------------------------------------+-------+-----------+----------+
+----+------+-----------+------+---------+------+-------------------+--------------------------------------------+----------+
| Id | User | Host | db | Command | Time | State | Info | Progress |
+----+------+-----------+------+---------+------+-------------------+--------------------------------------------+----------+
| 2 | root | localhost | nil | Query | 25 | copy to tmp table | ALTER TABLE nil_test ADD COLUMN phone1 int | 22.807 |
| 34 | root | localhost | NULL | Query | 0 | NULL | show processlist | 0.000 |
+----+------+-----------+------+---------+------+-------------------+--------------------------------------------+----------+
[root@percona-pxc3 nil]#
..............
.........
[root@percona-pxc3 nil]# mysql -uroot -proot -e "select ID, USER, HOST, DB, TIME, STATE, INFO, STAGE, MAX_STAGE, PROGRESS from information_schema.processlist where ID = 2; show processlist"
+----+------+-----------+------+------+-------------------+--------------------------------------------+-------+-----------+----------+
| ID | USER | HOST | DB | TIME | STATE | INFO | STAGE | MAX_STAGE | PROGRESS |
+----+------+-----------+------+------+-------------------+--------------------------------------------+-------+-----------+----------+
| 2 | root | localhost | nil | 54 | copy to tmp table | ALTER TABLE nil_test ADD COLUMN phone1 int | 1 | 2 | 98.300 |
+----+------+-----------+------+------+-------------------+--------------------------------------------+-------+-----------+----------+
+----+------+-----------+------+---------+------+-------------------+--------------------------------------------+----------+
| Id | User | Host | db | Command | Time | State | Info | Progress |
+----+------+-----------+------+---------+------+-------------------+--------------------------------------------+----------+
| 2 | root | localhost | nil | Query | 54 | copy to tmp table | ALTER TABLE nil_test ADD COLUMN phone1 int | 49.157 |
| 39 | root | localhost | NULL | Query | 0 | NULL | show processlist | 0.000 |
+----+------+-----------+------+---------+------+-------------------+--------------------------------------------+----------+
[root@percona-pxc3 nil]#
[root@percona-pxc3 nil]# mysql -uroot -proot -e "select ID, USER, HOST, DB, TIME, STATE, INFO, STAGE, MAX_STAGE, PROGRESS from information_schema.processlist where ID = 2; show processlist"
+----+------+-----------+------+------+-------+------+-------+-----------+----------+
| ID | USER | HOST | DB | TIME | STATE | INFO | STAGE | MAX_STAGE | PROGRESS |
+----+------+-----------+------+------+-------+------+-------+-----------+----------+
| 2 | root | localhost | nil | 0 | | NULL | 0 | 0 | 0.000 |
+----+------+-----------+------+------+-------+------+-------+-----------+----------+
+----+------+-----------+------+---------+------+-------+------------------+----------+
| Id | User | Host | db | Command | Time | State | Info | Progress |
+----+------+-----------+------+---------+------+-------+------------------+----------+
| 2 | root | localhost | nil | Sleep | 1 | | NULL | 0.000 |
| 40 | root | localhost | NULL | Query | 0 | NULL | show processlist | 0.000 |
+----+------+-----------+------+---------+------+-------+------------------+----------+
[root@percona-pxc3 nil]#

Conclusion: As we know, some ALTER TABLE can cause problems like server hang or crash. So whenever we are planning to run it on productions servers, it has to be well planned. As MySQL doesn’t provide a “progress bar,” we can use the above explained methods to check progress. If anyone knows of any other method aside from the above then please share in the comments and I would glad to add it in this post.

The post How to monitor ALTER TABLE progress in MySQL appeared first on MySQL Performance Blog.

Feb
25
2014
--

Fast-Growing 2U Files For $100M IPO, But Is It Poised To Be The Next Big Education Company?

When 2U emerged in 2008, online education was still struggling to be taken seriously. Despite steadily increasing online enrollment, many remained skeptical. Both fairly and unfairly, online education was seen as a world of simple micro-correspondence courses, limited in quality, incapable of producing outcomes truly commensurate with on-campus education and therefore merely a supplement, not a… Read More

Feb
25
2014
--

Box Picks Up Former Symantec CEO Enrique Salem As Special Adviser On Its Road To IPO

Today Box announced that it has picked up another Adult In The Room, increasing its leadership depth as it ramps towards a widely leaked, forthcoming initial public offering. Former Symantec CEO Enrique Salem will take on the role of Special Adviser to the growing company. Read More

Feb
25
2014
--

Samsung Introduces KNOX Marketplace, An Enterprise App Store Powered By AppDirect

Samsung is making a big push with its enterprise market appeal today, thanks to the introduction of the new Samsung KNOX Marketplace. This is a special mobile-focused digital software storefront that offers up business apps, IT provisioning and tools for tech managers working within large organizations. Samsung and partner AppDirect, which powers the marketplace, are aiming to give companies… Read More

Feb
25
2014
--

Quick review of InfiniDB 4

I’ve mentioned InfiniDB before in a previous post titled, “Star Schema Bechmark: InfoBright, InfiniDB and LucidDB,” but it’s been 4 years since that was published. Recently I evaluated column-storage solutions for Percona Cloud Tools and took another look at InfiniDB 4. There was the release of version 4, which I think is worth attention.

What is interesting in InfiniDB 4:

  • Fully OpenSource, GPLv2. There is no reserved features for Enterprise version
  • Multiple CPUs are used even for single query execution
  • WINDOW functions in SQL queries

What is WINDOW functions? In short, in regular SQL for a given row you can’t access to previous and next rows (at least not without complex SELF JOINS) and WINDOW function allows that.

As a basic example:

SELECT start_ts,
       query_time,
       LAG(query_time) OVER (ORDER BY start_ts) prev_time
FROM   qc
WHERE  agent_id = 1;

So for given row (start_ts) we access not only current query_time, but also a previous query_time: LAG(query_time). So the result looks like:

start_ts       | query_time     | prev_sum
---------------------+----------------+----------
 2013-06-18 22:55:00 |       0.281992 |
 2013-06-18 23:00:00 |       0.292305 | 0.281992
 2013-06-18 23:05:00 |       0.215658 | 0.292305
 2013-06-18 23:10:00 |       0.243597 | 0.215658
 2013-06-18 23:15:00 |        0.35189 | 0.243597
 2013-06-18 23:20:00 |       0.543079 |  0.35189
 2013-06-18 23:25:00 |       0.495779 | 0.543079
 2013-06-18 23:30:00 |       0.589326 | 0.495779
 2013-06-18 23:35:00 |       0.210907 | 0.589326
 2013-06-18 23:40:00 |       0.167944 | 0.210907
 2013-06-18 23:45:00 |       0.202401 | 0.167944
 2013-06-18 23:50:00 |       0.171676 | 0.202401
 2013-06-18 23:55:00 |       0.234001 | 0.171676
 2013-06-19 00:00:00 |       0.214086 | 0.234001

It gives a lot of interesting possibilities, like calculation of a growth or decline for time periods.

I still continue to evaluate different solutions but I decided to share this about InfiniDB, as it looks quite interesting now.

The post Quick review of InfiniDB 4 appeared first on MySQL Performance Blog.

Powered by WordPress | Theme: Aeros 2.0 by TheBuckmaker.com