This is a post about SYSDATE()
and NOW()
and CURRENT_TIMESTAMP()
functions in MySQL.
Firstly, note is that of these three, only CURRENT_TIMESTAMP()
is part of the SQL Standard. NOW()
happens to be an alias for CURRENT_TIMESTAMP()
in MySQL.
Secondly, note that replication does not work well with non-deterministic functions. And “hey, what time is it?” is non-deterministic. Ask it twice, with a second apart between asking, and both times you get different results (with at least second precision).
You can start to see the problem here….but there’s more…. (more…)
This is a post about SYSDATE()
and NOW()
and CURRENT_TIMESTAMP()
functions in MySQL.
Firstly, note is that of these three, only CURRENT_TIMESTAMP()
is part of the SQL Standard. NOW()
happens to be an alias for CURRENT_TIMESTAMP()
in MySQL.
Secondly, note that replication does not work well with non-deterministic functions. And “hey, what time is it?” is non-deterministic. Ask it twice, with a second apart between asking, and both times you get different results (with at least second precision).
You can start to see the problem here….but there’s more…. (more…)
The unsung heroes of InnoDB are the logfiles. They are what makes InnoDB automatic crash recovery possible.
Database administrators of other DBMS may be familiar with the concept of a “redo” log. When data is changed, affected data pages are changed in the innodb_buffer_pool. Then, the change is written to the redo log, which in MySQL is the InnoDB logfile (ib_logfile0 and ib_logfile1). The pages are marked as “dirty”, and eventually get flushed and written to disk.
If MySQL crashes, there may be data that is changed that has not been written to disk. Those data pages were marked as “dirty” in the innodb_buffer_pool, but after a MySQL crash the innodb_buffer_pool no longer exists. However, they were written to the redo log. On crash recovery, MySQL can read the redo log (InnoDB log files) and apply any changes that were not written to disk.
That is the basic functionality of the InnoDB log files. Given this, let’s look at some of the different parameters and their ramifications.
innodb_log_files_in_group
is set with a default of 2. The logfiles are written in a circular manner — ib_logfile0 is written first, and when it has reached its maximum size, then ib_logfile1 will be written to.
innodb_log_file_size
is the size of each log file in the log group. The total, combined size of all the log files has to be less than 4 Gb (according to the MySQL manual). Because the logfiles contain changes in the buffer pool that have not been written to disk, the total, combined size of all the log files should not be more than the innodb_buffer_pool_size.
If all the log files in the group are full of changes that have not been written to disk, MySQL will start to flush dirty pages from the InnoDB buffer pool, writing the changes to disk. If the log files are small, changes will be written to disk more often, which can cause more disk I/O.
When InnoDB does a crash recovery, it reads the log files. If the log files are large, it will take longer to recover from a crash. If innodb_fast_shutdown
is set to 0, the log files are purged when MySQL shuts down — larger files mean a longer shutdown time. The default for innodb_fast_shutdown
is 1, which means that the log files are not purged before a shutdown. Starting in MySQL 5.0.5, you can set it to 2, which simulates a crash, and at the next startup InnoDB will do a crash recovery.
innodb_flush_log_at_trx_commit
controls how often the log files are written to. A value of 0 causes the log files to be written and flushed to disk once per second. The default is 1, which causes the log buffer to be written and flushed to disk after every transaction commit. The value can also be set to 2, which causes the log buffer to be written after every transaction commit and flushes the log files to disk once per second. A value of 2 means that MySQL might think that some changes are written to the log file, but do not persist in the log file after an operating system crash, because the log file was not flushed to disk before a crash.
Note that some filesystems are not honest about flushing to disk, so even though you may have the default value of 1, your system may be acting as if it has a value of 2. Setting this parameter to 2 means that there will be less I/O, at the cost of not being able to recover data from a crash.
innodb_flush_method
changes how InnoDB opens and flushes data and log files. See the manual for details; the end result is a tradeoff in I/O performance versus whether or not an operating system crash would leave the InnoDB log files in an inconsistent state.
innodb_log_buffer_size
is the write buffer for InnoDB log files. The larger the buffer is, the less often the log files are written to. This can save I/O.
The unsung heroes of InnoDB are the logfiles. They are what makes InnoDB automatic crash recovery possible.
Database administrators of other DBMS may be familiar with the concept of a “redo” log. When data is changed, affected data pages are changed in the innodb_buffer_pool. Then, the change is written to the redo log, which in MySQL is the InnoDB logfile (ib_logfile0 and ib_logfile1). The pages are marked as “dirty”, and eventually get flushed and written to disk.
If MySQL crashes, there may be data that is changed that has not been written to disk. Those data pages were marked as “dirty” in the innodb_buffer_pool, but after a MySQL crash the innodb_buffer_pool no longer exists. However, they were written to the redo log. On crash recovery, MySQL can read the redo log (InnoDB log files) and apply any changes that were not written to disk.
That is the basic functionality of the InnoDB log files. Given this, let’s look at some of the different parameters and their ramifications.
innodb_log_files_in_group
is set with a default of 2. The logfiles are written in a circular manner — ib_logfile0 is written first, and when it has reached its maximum size, then ib_logfile1 will be written to.
innodb_log_file_size
is the size of each log file in the log group. The total, combined size of all the log files has to be less than 4 Gb (according to the MySQL manual). Because the logfiles contain changes in the buffer pool that have not been written to disk, the total, combined size of all the log files should not be more than the innodb_buffer_pool_size.
If all the log files in the group are full of changes that have not been written to disk, MySQL will start to flush dirty pages from the InnoDB buffer pool, writing the changes to disk. If the log files are small, changes will be written to disk more often, which can cause more disk I/O.
When InnoDB does a crash recovery, it reads the log files. If the log files are large, it will take longer to recover from a crash. If innodb_fast_shutdown
is set to 0, the log files are purged when MySQL shuts down — larger files mean a longer shutdown time. The default for innodb_fast_shutdown
is 1, which means that the log files are not purged before a shutdown. Starting in MySQL 5.0.5, you can set it to 2, which simulates a crash, and at the next startup InnoDB will do a crash recovery.
innodb_flush_log_at_trx_commit
controls how often the log files are written to. A value of 0 causes the log files to be written and flushed to disk once per second. The default is 1, which causes the log buffer to be written and flushed to disk after every transaction commit. The value can also be set to 2, which causes the log buffer to be written after every transaction commit and flushes the log files to disk once per second. A value of 2 means that MySQL might think that some changes are written to the log file, but do not persist in the log file after an operating system crash, because the log file was not flushed to disk before a crash.
Note that some filesystems are not honest about flushing to disk, so even though you may have the default value of 1, your system may be acting as if it has a value of 2. Setting this parameter to 2 means that there will be less I/O, at the cost of not being able to recover data from a crash.
innodb_flush_method
changes how InnoDB opens and flushes data and log files. See the manual for details; the end result is a tradeoff in I/O performance versus whether or not an operating system crash would leave the InnoDB log files in an inconsistent state.
innodb_log_buffer_size
is the write buffer for InnoDB log files. The larger the buffer is, the less often the log files are written to. This can save I/O.
As I putter around the MySQL INFORMATION_SCHEMA
, I am finding lots of undocumented behavior for fields that should be straightforward. For example, the VIEWS
table holds information about views, and the VIEW_DEFINITION
field contains the view definition, right?
Well, when I was looking at the VIEW_DEFINITION
today, I noticed an odd thing. Even though I had permissions to see the view definition (as proven by the SHOW CREATE VIEW
command), the INFORMATION_SCHEMA.VIEWS
table sometimes came up blank for the VIEW_DEFINITION
. I had to figure out why, and now that I know, I’m not sure if it’s a bug or a feature…..can you figure it out?
mysql> USE INFORMATION_SCHEMA;
Database changed
mysql> SELECT TABLE_NAME,VIEW_DEFINITION FROM VIEWS WHERE TABLE_SCHEMA='sakila';
+----------------------------+-----------------+
| TABLE_NAME | VIEW_DEFINITION |
+----------------------------+-----------------+
| actor_info | |
| customer_list | |
| film_list | |
| nicer_but_slower_film_list | |
| sales_by_film_category | |
| sales_by_store | |
| staff_list | |
+----------------------------+-----------------+
7 rows in set (0.16 sec)
mysql> SHOW CREATE VIEW sakila.actor_info\G
*************************** 1. row ***************************
View: actor_info
Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL
SECURITY INVOKER VIEW `sakila`.`actor_info` AS select `a`.`actor_id` AS `actor_i
d`,`a`.`first_name` AS `first_name`,`a`.`last_name` AS `last_name`,group_concat(
distinct concat(`c`.`name`,': ',(select group_concat(`f`.`title` order by `f`.`t
itle` ASC separator ', ') AS `GROUP_CONCAT(f.title ORDER BY f.title SEPARATOR ',
')` from ((`sakila`.`film` `f` join `sakila`.`film_category` `fc` on((`f`.`film
_id` = `fc`.`film_id`))) join `sakila`.`film_actor` `fa` on((`f`.`film_id` = `fa
`.`film_id`))) where ((`fc`.`category_id` = `c`.`category_id`) and (`fa`.`actor_
id` = `a`.`actor_id`)))) order by `c`.`name` ASC separator '; ') AS `film_info`
from (((`sakila`.`actor` `a` left join `sakila`.`film_actor` `fa` on((`a`.`actor
_id` = `fa`.`actor_id`))) left join `sakila`.`film_category` `fc` on((`fa`.`film
_id` = `fc`.`film_id`))) left join `sakila`.`category` `c` on((`fc`.`category_id
` = `c`.`category_id`))) group by `a`.`actor_id`,`a`.`first_name`,`a`.`last_name
`
character_set_client: latin1
collation_connection: latin1_swedish_ci
1 row in set (0.02 sec)
mysql> SHOW CREATE VIEW sakila.customer_list\G
*************************** 1. row ***************************
View: customer_list
Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL
SECURITY DEFINER VIEW `sakila`.`customer_list` AS select `cu`.`customer_id` AS `
ID`,concat(`cu`.`first_name`,_utf8' ',`cu`.`last_name`) AS `name`,`a`.`address`
AS `address`,`a`.`postal_code` AS `zip code`,`a`.`phone` AS `phone`,`sakila`.`ci
ty`.`city` AS `city`,`sakila`.`country`.`country` AS `country`,if(`cu`.`active`,
_utf8'active',_utf8'') AS `notes`,`cu`.`store_id` AS `SID` from (((`sakila`.`cus
tomer` `cu` join `sakila`.`address` `a` on((`cu`.`address_id` = `a`.`address_id`
))) join `sakila`.`city` on((`a`.`city_id` = `sakila`.`city`.`city_id`))) join `
sakila`.`country` on((`sakila`.`city`.`country_id` = `sakila`.`country`.`country
_id`)))
character_set_client: latin1
collation_connection: latin1_swedish_ci
1 row in set (0.00 sec)
mysql>
(some people read the dictionary, I read the data dictionary!)
As I putter around the MySQL INFORMATION_SCHEMA
, I am finding lots of undocumented behavior for fields that should be straightforward. For example, the VIEWS
table holds information about views, and the VIEW_DEFINITION
field contains the view definition, right?
Well, when I was looking at the VIEW_DEFINITION
today, I noticed an odd thing. Even though I had permissions to see the view definition (as proven by the SHOW CREATE VIEW
command), the INFORMATION_SCHEMA.VIEWS
table sometimes came up blank for the VIEW_DEFINITION
. I had to figure out why, and now that I know, I’m not sure if it’s a bug or a feature…..can you figure it out?
mysql> USE INFORMATION_SCHEMA;
Database changed
mysql> SELECT TABLE_NAME,VIEW_DEFINITION FROM VIEWS WHERE TABLE_SCHEMA='sakila';
+----------------------------+-----------------+
| TABLE_NAME | VIEW_DEFINITION |
+----------------------------+-----------------+
| actor_info | |
| customer_list | |
| film_list | |
| nicer_but_slower_film_list | |
| sales_by_film_category | |
| sales_by_store | |
| staff_list | |
+----------------------------+-----------------+
7 rows in set (0.16 sec)
mysql> SHOW CREATE VIEW sakila.actor_info\G
*************************** 1. row ***************************
View: actor_info
Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL
SECURITY INVOKER VIEW `sakila`.`actor_info` AS select `a`.`actor_id` AS `actor_i
d`,`a`.`first_name` AS `first_name`,`a`.`last_name` AS `last_name`,group_concat(
distinct concat(`c`.`name`,': ',(select group_concat(`f`.`title` order by `f`.`t
itle` ASC separator ', ') AS `GROUP_CONCAT(f.title ORDER BY f.title SEPARATOR ',
')` from ((`sakila`.`film` `f` join `sakila`.`film_category` `fc` on((`f`.`film
_id` = `fc`.`film_id`))) join `sakila`.`film_actor` `fa` on((`f`.`film_id` = `fa
`.`film_id`))) where ((`fc`.`category_id` = `c`.`category_id`) and (`fa`.`actor_
id` = `a`.`actor_id`)))) order by `c`.`name` ASC separator '; ') AS `film_info`
from (((`sakila`.`actor` `a` left join `sakila`.`film_actor` `fa` on((`a`.`actor
_id` = `fa`.`actor_id`))) left join `sakila`.`film_category` `fc` on((`fa`.`film
_id` = `fc`.`film_id`))) left join `sakila`.`category` `c` on((`fc`.`category_id
` = `c`.`category_id`))) group by `a`.`actor_id`,`a`.`first_name`,`a`.`last_name
`
character_set_client: latin1
collation_connection: latin1_swedish_ci
1 row in set (0.02 sec)
mysql> SHOW CREATE VIEW sakila.customer_list\G
*************************** 1. row ***************************
View: customer_list
Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL
SECURITY DEFINER VIEW `sakila`.`customer_list` AS select `cu`.`customer_id` AS `
ID`,concat(`cu`.`first_name`,_utf8' ',`cu`.`last_name`) AS `name`,`a`.`address`
AS `address`,`a`.`postal_code` AS `zip code`,`a`.`phone` AS `phone`,`sakila`.`ci
ty`.`city` AS `city`,`sakila`.`country`.`country` AS `country`,if(`cu`.`active`,
_utf8'active',_utf8'') AS `notes`,`cu`.`store_id` AS `SID` from (((`sakila`.`cus
tomer` `cu` join `sakila`.`address` `a` on((`cu`.`address_id` = `a`.`address_id`
))) join `sakila`.`city` on((`a`.`city_id` = `sakila`.`city`.`city_id`))) join `
sakila`.`country` on((`sakila`.`city`.`country_id` = `sakila`.`country`.`country
_id`)))
character_set_client: latin1
collation_connection: latin1_swedish_ci
1 row in set (0.00 sec)
mysql>
(some people read the dictionary, I read the data dictionary!)
A while ago, MySQL developed a Community Contribution Agreement for community contributions to the MySQL source code. While browsing the MySQL Forge Wiki I cam across:
http://forge.mysql.com/wiki/Community_Contributions
This page shows that the Community Contribution Agreement has changed — it is no longer the document MySQL AB created. It is now Sun Microsystem’s standard Sun Contributor Agreement, which CEO Mårten Mickos recently explained to me was “more accepted than the agreement MySQL had come up with.”
I am happy to see some of the great Sun practices trickle down to replace some issues that MySQL did not handle smoothly. All in all, I agree with Mårten Mickos and think the Sun Contributor Agreement is much better….
….but what do you think?
A while ago, MySQL developed a Community Contribution Agreement for community contributions to the MySQL source code. While browsing the MySQL Forge Wiki I cam across:
http://forge.mysql.com/wiki/Community_Contributions
This page shows that the Community Contribution Agreement has changed — it is no longer the document MySQL AB created. It is now Sun Microsystem’s standard Sun Contributor Agreement, which CEO Mårten Mickos recently explained to me was “more accepted than the agreement MySQL had come up with.”
I am happy to see some of the great Sun practices trickle down to replace some issues that MySQL did not handle smoothly. All in all, I agree with Mårten Mickos and think the Sun Contributor Agreement is much better….
….but what do you think?
Gavin Newsome, mayor of San Francisco, and Ed Begley, Jr. talk about being green, and commend Oracle and Oracle OpenWorld for being green.
Watch the video online or download the 19 Mb flash video file
Watch the video online or download the 18 Mb flash video file
(more…)
Gavin Newsome, mayor of San Francisco, and Ed Begley, Jr. talk about being green, and commend Oracle and Oracle OpenWorld for being green.
Watch the video online or download the 19 Mb flash video file
Watch the video online or download the 18 Mb flash video file
(more…)
To start off the conference, the first keynote at Oracle OpenWorld took a break from technology and veered into the world of politics. The official conference description says:
Washington’s best-loved political couple Mary Matalin and James Carville entertain the crowd with a bitingly humorous look at the world of politics.
Indeed, there was humor, and politics. For a light-hearted yet factual look at US politics, watch the video by streaming directly in your browser or download the 176 Mb Flash video file.
(more…)
To start off the conference, the first keynote at Oracle OpenWorld took a break from technology and veered into the world of politics. The official conference description says:
Washington’s best-loved political couple Mary Matalin and James Carville entertain the crowd with a bitingly humorous look at the world of politics.
Indeed, there was humor, and politics. For a light-hearted yet factual look at US politics, watch the video by streaming directly in your browser or download the 176 Mb Flash video file.
(more…)
Note: This article is about the WHERE
extension to SHOW
. I specifically use SHOW STATUS
as an example, but WHERE
is an extension to many SHOW
statements.
Often DBAs will assess the health of a system by looking at some of the status variables returned by SHOW GLOBAL STATUS
(specifying GLOBAL
is important; remember that SHOW STATUS
is the same as SHOW SESSION STATUS
).
There are many status variables that SHOW GLOBAL STATUS
returns. (SHOW GLOBAL STATUS
on a Windows machine, MySQL version 5.0.67 returned 249, 5.1.22 returned 256 and 6.0.6-alpha returned 295 status variables!). I have used the SHOW STATUS LIKE
syntax to help give me the output I really want, particularly when I forget the exact names of the status variables I am looking for.
But I did not know of a way to perform SHOW STATUS NOT LIKE
or have any other means of filtering the information. Until today, when I was reading up on SHOW STATUS
.
(more…)
Note: This article is about the WHERE
extension to SHOW
. I specifically use SHOW STATUS
as an example, but WHERE
is an extension to many SHOW
statements.
Often DBAs will assess the health of a system by looking at some of the status variables returned by SHOW GLOBAL STATUS
(specifying GLOBAL
is important; remember that SHOW STATUS
is the same as SHOW SESSION STATUS
).
There are many status variables that SHOW GLOBAL STATUS
returns. (SHOW GLOBAL STATUS
on a Windows machine, MySQL version 5.0.67 returned 249, 5.1.22 returned 256 and 6.0.6-alpha returned 295 status variables!). I have used the SHOW STATUS LIKE
syntax to help give me the output I really want, particularly when I forget the exact names of the status variables I am looking for.
But I did not know of a way to perform SHOW STATUS NOT LIKE
or have any other means of filtering the information. Until today, when I was reading up on SHOW STATUS
.
(more…)
Smithy commented on my blog post about the rumor of Monty leaving Sun with a pointer to an article on ComputerWorld Finland that mentions:
Widenius told to Computerworld Finland on Friday that negotiations are still on.
Meanwhile, Matt Asay, who seems to think Monty actually has left Sun (even though all other reports have been clear to mention that this is unconfirmed), writes of a new investment Monty has made.
Last week I speculated about the impact of Monty leaving Sun. In the end, if he does stay, it’s wonderful for Sun. If he leaves, he will no doubt go on to continue to be wonderful for the database community at large, much like Jim Starkey.
But until Monty Says, nothing is official.
Smithy commented on my blog post about the rumor of Monty leaving Sun with a pointer to an article on ComputerWorld Finland that mentions:
Widenius told to Computerworld Finland on Friday that negotiations are still on.
Meanwhile, Matt Asay, who seems to think Monty actually has left Sun (even though all other reports have been clear to mention that this is unconfirmed), writes of a new investment Monty has made.
Last week I speculated about the impact of Monty leaving Sun. In the end, if he does stay, it’s wonderful for Sun. If he leaves, he will no doubt go on to continue to be wonderful for the database community at large, much like Jim Starkey.
But until Monty Says, nothing is official.
ValleyWag reports that MySQL’s Monty Widenius is no longer “MySQL’s”. Some folks have known that Monty has not been happy in his current position; this leads me to believe the rumor is true (though of course an official announcement is the only confirmation).
So what does this mean for MySQL? Well, honestly, if a product falls apart because one out of 300 employees leaves, it was probably doomed anyway. There are plenty of capable employees left, and being owned by Sun means that there are many more resources they can tap as well.
What will the official company announcement be? My prediction is (more…)
ValleyWag reports that MySQL’s Monty Widenius is no longer “MySQL’s”. Some folks have known that Monty has not been happy in his current position; this leads me to believe the rumor is true (though of course an official announcement is the only confirmation).
So what does this mean for MySQL? Well, honestly, if a product falls apart because one out of 300 employees leaves, it was probably doomed anyway. There are plenty of capable employees left, and being owned by Sun means that there are many more resources they can tap as well.
What will the official company announcement be? My prediction is (more…)
I confess — I have not always been an exclusive MySQL user. I have fooled around with other DBMSs. I was young, inexperienced, and I needed the money, I swear!
This comes about because I was doing some electronic de-crufting….From a file last modified on 10:50 am on 2005-06-30:
> more addcatalog.sh
#!/bin/sh
db2 catalog tcpip node $1 remote $2 server 50000
db2 terminate
db2 catalog database sample as $2 at node $1
db2 terminate
# [db2inst1@midgard db2inst1]$ db2sql92 -a db2inst3/password -d coworkername
And from the same time-frame there’s also:
(more…)
I confess — I have not always been an exclusive MySQL user. I have fooled around with other DBMSs. I was young, inexperienced, and I needed the money, I swear!
This comes about because I was doing some electronic de-crufting….From a file last modified on 10:50 am on 2005-06-30:
> more addcatalog.sh
#!/bin/sh
db2 catalog tcpip node $1 remote $2 server 50000
db2 terminate
db2 catalog database sample as $2 at node $1
db2 terminate
# [db2inst1@midgard db2inst1]$ db2sql92 -a db2inst3/password -d coworkername
And from the same time-frame there’s also:
(more…)