Date Range using ExtJS Date Field and Advanced VType

2009年6月27日 lalfa.shi 没有评论

Introduction:

Date Ranging is simple using ExtJS DateField. Yes! When I was working for one of my project, In one of my form I got to include Date Range functionality. When I was searching for this functionality, I got an answer from ExtJS forums, I followed one thread and got the answer. Here is the respective thread, which I was talking about. -problem with custom VTypes – daterange, if you drill down on the same page, you can view a link which depicts about the advance vtype by Brian. So, you can grab the latest version of advance vtypes here - vtypes

PreviewDownload

Code Courtesy for vtypes – ExtJS and Brian

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Add the additional 'advanced' VTypes
Ext.apply(Ext.form.VTypes, {
    daterange : function(val, field) {
        var date = field.parseDate(val);

        if(!date){
            return;
        }
        if (field.startDateField && (!this.dateRangeMax || (date.getTime() != this.dateRangeMax.getTime()))) {
            var start = Ext.getCmp(field.startDateField);
            start.setMaxValue(date);
            start.validate();
            this.dateRangeMax = date;
        }
        else if (field.endDateField && (!this.dateRangeMin || (date.getTime() != this.dateRangeMin.getTime()))) {
            var end = Ext.getCmp(field.endDateField);
            end.setMinValue(date);
            end.validate();
            this.dateRangeMin = date;
        }
        /*
         * Always return true since we're only using this vtype to set the
         * min/max allowed values (these are tested for after the vtype test)
         */
        return true;
    }
});

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Add the additional ‘advanced’ VTypes
Ext.apply(Ext.form.VTypes, {
daterange : function(val, field) {
var date = field.parseDate(val);
if(!date){
return;
}
if (field.startDateField && (!this.dateRangeMax || (date.getTime() != this.dateRangeMax.getTime()))) {
var start = Ext.getCmp(field.startDateField);
start.setMaxValue(date);
start.validate();
this.dateRangeMax = date;
}
else if (field.endDateField && (!this.dateRangeMin || (date.getTime() != this.dateRangeMin.getTime()))) {
var end = Ext.getCmp(field.endDateField);
end.setMinValue(date);
end.validate();
this.dateRangeMin = date;
}
/*
* Always return true since we’re only using this vtype to set the
* min/max allowed values (these are tested for after the vtype test)
*/
return true;
}
});

Below is the required example:

1
2
3
4
5
6
7
8
9
<div>
  <div style="float:left;"><strong>From</strong><br />
    <div id="fromdate"></div>
  </div>
  <div style="float:left; padding-left:20px;"><strong>To</strong><br />
    <div id="todate"></div>
  </div>
  <div style="clear:both"></div>
</div>

Respective ExtJS JavaScript Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<script language="javascript">
// Add the additional 'advanced' VTypes -- [Begin]
Ext.apply(Ext.form.VTypes, {
	daterange : function(val, field) {
		var date = field.parseDate(val);

		if(!date){
			return;
		}
		if (field.startDateField && (!this.dateRangeMax || (date.getTime() != this.dateRangeMax.getTime()))) {
			var start = Ext.getCmp(field.startDateField);
			start.setMaxValue(date);
			start.validate();
			this.dateRangeMax = date;
		}
		else if (field.endDateField && (!this.dateRangeMin || (date.getTime() != this.dateRangeMin.getTime()))) {
			var end = Ext.getCmp(field.endDateField);
			end.setMinValue(date);
			end.validate();
			this.dateRangeMin = date;
		}
		/*
		 * Always return true since we're only using this vtype to set the
		 * min/max allowed values (these are tested for after the vtype test)
		 */
		return true;
	}
});
// Add the additional 'advanced' VTypes -- [End]

dateRangeFunc();
function dateRangeFunc()
	{
		// Date picker				
		var fromdate = new Ext.form.DateField({
			format: 'Y-M-d', //YYYY-MMM-DD
			fieldLabel: '',
			id: 'startdt',
			name: 'startdt',
			width:140,
			allowBlank:false,
			vtype: 'daterange',
            endDateField: 'enddt'// id of the 'To' date field
		});

		var todate = new Ext.form.DateField({
			format: 'Y-M-d', //YYYY-MMM-DD
			fieldLabel: '',
			id: 'enddt',
			name: 'enddt',
			width:140,
			allowBlank:false,
			vtype: 'daterange',
            startDateField: 'startdt'// id of the 'From' date field
		});

		fromdate.render('fromdate');
		todate.render('todate');
} //dateRangeFunc() close
</script>

daterange

Below is the working example for the same:

Preview – Date Range using ExtJS Date Field

Download:

Download – Date Range using ExtJS Date Field

分类: AJAX 标签:

使用Xtrabackup备份MySQL数据库

2009年6月26日 lalfa.shi 没有评论

原本地址:http://www.ningoo.net/html/2009/using_xtrabackup_backup_mysql_database.html

MySQL数据库的备份,一直是个比较头痛的问题。各种工具虽然不少,但一个真正好用易用的,却又非常难找。Mysqldump做为数据的逻辑备份工具还行,但是无法进行在线热备,而没有物理备份工具,在数据量比较大的时候,恢复的时间也会长得无法接受。InnoDB倒是有个商业的InnoDB Hotbackup,可以对InnoDB引擎的表实现在线热备。最近发现了一个工具,percona出品的Xtrabackup,是InnoDB Hotbackup的一个开源替代品,可以在线对InnoDB/XtraDB引擎的表进行物理备份,试用了一下,非常的不错,值得向MySQL DBA们推荐。

下面是一个实际备份的例子,采用了gzip将备份流进行压缩,约20GB的数据库,压缩后大小为340MB,当然,压缩后的大小跟数据库中实际使用的空间是相关的。备份时间约6分44秒。

innobackupex是参考了InnoDB Hotbackup的innoback脚本修改而来的,主要是为了方便的同时备份InnoDB和MyISAM引擎的表,并且加入了一些使用的选项。如–slave-info可以记录备份恢复后,作为slave需要的一些信息,根据这些信息,可以很方便的利用备份来重做slave。

注意,从备份后的tar包解包的时候,需要使用-i参数。最新发布的是0.7版,猛击这里下载

$innobackupex-1.5.1 --user=root --stream=tar /bak/ --slave-info | gzip > /bak/bak_mysql.tar.gz

InnoDB Backup Utility v1.5.1-xtrabackup; Copyright 2003, 2009 Innobase Oy.
All Rights Reserved.

This software is published under
the GNU GENERAL PUBLIC LICENSE Version 2, June 1991.

IMPORTANT: Please check that the backup run completes successfully.
At the end of a successful backup run innobackup
prints "innobackup completed OK!".

innobackupex: Using mysql Ver 14.12 Distrib 5.0.67, for redhat-linux-gnu (x86_64)
using EditLine wrapper
innobackupex: Using mysql server version 5.0.67-log

innobackupex: Created backup directory /bak
090625 15:23:00 innobackupex: Starting mysql with options: --unbuffered --user=root
090625 15:23:00 innobackupex: Connected to database with mysql child process (pid=3431)
090625 15:23:04 innobackupex: Connection to database server closed

090625 15:23:04 innobackupex: Starting ibbackup with command:
xtrabackup --backup --suspend-at-end --log-stream --target-dir=./
innobackupex: Waiting for ibbackup (pid=3565) to suspend
innobackupex: Suspend file '/opt/mysqldata/xtrabackup_suspended'

xtrabackup: suspend-at-end is enabled.
xtrabackup: uses posix_fadvise().
xtrabackup: cd to /opt/mysqldata
xtrabackup: Target instance is assumed as followings.
xtrabackup: innodb_data_home_dir = /opt/mysqldata
xtrabackup: innodb_data_file_path = ibdata1:10G;ibdata2:10G
xtrabackup: innodb_log_group_home_dir = ./
xtrabackup: innodb_log_files_in_group = 4
xtrabackup: innodb_log_file_size = 104857600
xtrabackup: use O_DIRECT
xtrabackup: Stream mode.
>> log scanned up to (0 3053406941)

090625 15:23:06 innobackupex: Continuing after ibbackup has suspended

innobackupex: Starting to backup InnoDB tables and indexes
innobackupex: from original InnoDB data directory '/opt/mysqldata'
innobackupex: Backing up as tar stream 'ibdata1'
>> log scanned up to (0 3053416714)
...这里省略若干行
>> log scanned up to (0 3054123851)
tar: ibdata1: file changed as we read it
innobackupex: Backing up as tar stream 'ibdata2'
>> log scanned up to (0 3054142116)
...这里省略若干行
>> log scanned up to (0 3054618483)
innobackupex: Backing up file '/opt/mysqldata/test/sp.ibd'
innobackupex: Backing up file '/opt/mysqldata/test/tmp_dy.ibd'
innobackupex: Backing up files '/opt/mysqldata/testdb/*.ibd' (206 files)
>> log scanned up to (0 3054638401)
>> log scanned up to (0 3054668860)
tar: testdb/group_group_thread_0027.ibd: file changed as we read it
>> log scanned up to (0 3054695015)
>> log scanned up to (0 3054928216)
tar: testdb/group_thread_reply_0007.ibd: file changed as we read it
>> log scanned up to (0 3054952588)
>> log scanned up to (0 3055005439)
tar: testdb/group_user_0001.ibd: file changed as we read it
>> log scanned up to (0 3055028610)
>> log scanned up to (0 3055044650)
tar: testdb/group_user_0006.ibd: file changed as we read it
>> log scanned up to (0 3055060461)
innobackupex: Backing up file '/opt/mysqldata/testdb/comments.ibd'
innobackupex: Backing up file '/opt/mysqldata/testdb/testdb.ibd'
innobackupex: Backing up file '/opt/mysqldata/testdb/testdb_content.ibd'
innobackupex: Backing up file '/opt/mysqldata/testdb/testdb_ids.ibd'
090625 15:29:17 innobackupex: Starting mysql with options: --unbuffered --user=root
090625 15:29:17 innobackupex: Connected to database with mysql child process (pid=5458)
>> log scanned up to (0 3055072495)
090625 15:29:21 innobackupex: Starting to lock all tables...
>> log scanned up to (0 3055087148)
>> log scanned up to (0 3055119993)
090625 15:29:39 innobackupex: All tables locked and flushed to disk

090625 15:29:39 innobackupex: Starting to backup .frm, .MRG, .MYD, .MYI,
innobackupex: .TRG, .TRN, and .opt files in
innobackupex: subdirectories of '/opt/mysqldata'
innobackupex: Backing up file '/opt/mysqldata/test/sp.frm'
innobackupex: Backing up file '/opt/mysqldata/test/tmp_dy.frm'
innobackupex: Backing up files '/opt/mysqldata/testdb/*.{frm,MYD,MYI,MRG,TRG,TRN,opt}' (207 files)
innobackupex: Backing up file '/opt/mysqldata/testdb/comments.frm'
innobackupex: Backing up file '/opt/mysqldata/testdb/testdb.frm'
innobackupex: Backing up file '/opt/mysqldata/testdb/testdb_content.frm'
innobackupex: Backing up file '/opt/mysqldata/testdb/testdb_ids.frm'
innobackupex: Backing up file '/opt/mysqldata/testdb/db.opt'
innobackupex: Backing up files '/opt/mysqldata/mysql/*.{frm,MYD,MYI,MRG,TRG,TRN,opt}' (52 files)
090625 15:29:40 innobackupex: Finished backing up .frm, .MRG, .MYD, .MYI, .TRG, .TRN, and .opt files

innobackupex: Resuming ibbackup

xtrabackup: The latest check point (for incremental): '0:3054881736'
>> log scanned up to (0 3055120013)
xtrabackup: Transaction log of lsn (0 3053102766) to (0 3055120013) was copied.
090625 15:29:44 innobackupex: All tables unlocked
090625 15:29:44 innobackupex: Connection to database server closed

innobackupex: Backup created in directory '/bak/'
innobackupex: MySQL binlog position: filename '', position
innobackupex: MySQL slave binlog position: master host '127.0.0.1',
filename 'mysql-bin.000006', position 227207755
090625 15:29:44 innobackupex: innobackup completed OK!
innobackupex: You must use -i (--ignore-zeros) option for extraction of the tar stream.

分类: Database 标签:

Debugging MySQL Stored Procedures

2009年6月23日 lalfa.shi 1 条评论
Stored Procedures are programs that execute within a database server. They are usually written in a database language such as PL/SQL or ANSI SQL:2003 SQL/PSM. (Granted, some database servers do support Java stored procedures, but I don’t examine them here.) There are any number of books for learning to write Stored Procedures — MySQL Stored Procedure Programming, by Guy Harrison, and Teach Yourself PL/SQL in 21 Days,by Jonathan Gennick and Tom Luers, come to mind), but there are a handful of general reasons to write code in a stored procedure:
The logic being implemented might be database logic and so a database language is closer to the problem domain than a general purpose language like Java.
A stored procedure can be significantly faster than a Java program which might make multiple calls to the database.
A stored procedure can be more secure.
Regardless of the reasons for choosing to write a stored procedure, the problem remains of how to debug one. What if you could debug in both development and production at little to no cost to the performance of the Stored Procedures? Traditional debuggers do not generally work with stored procedures which can leave a developer with a fast and broken procedure executing within their database server.
Approaches That Don’t Work
Debug the SQL in your Stored Procedure. This approach works on the assumption the main logic of your Stored Procedures is the actual DDL and DML within the procedure, in other words, the queries, inserts and so on. It assumes that the rest of the Stored Procedures is largely scaffolding to support the database operations. In many cases this is a valid assumption, after all if the Stored Procedure wasn’t manipulating the database you probably wouldn’t have written it as a Stored Procedure.
It goes without saying that regardless of how much non-SQL code you have in your Stored Procedures you need to validate the SQL itself, especially since this level of testing can be relatively straightforward. It can be as simple as starting your database command line tool (or query browser for the gui inclined) and pasting in the guts of your SQL statements to verify correctness. This of course goes beyond simple syntactic correctness, you must validate the semantic correctness as well.
In some cases however it’s not quite that simple, for a couple of classes of reasons. First, your SQL code can (and usually will) rely on variables and parameters that have been defined and/or manipulated by the Stored Procedures. If you have a select statement that stored its results into a variable, and then a later SQL statement that uses that variable, then your “paste the sql into the command line” approach of testing gets a bit harder. You have to insert the one or more statements, execute them, perhaps creating temporary variables along the way, and possibly modify the SQL you are actually trying to test. This happens by degree but you can certainly reach a point where it’s clear that you’re no longer testing the SQL you started with.
The second class of problem with this approach is that often the logic of the Stored Procedures lives in the procedural code of the procedure and not in the SQL statements themselves. SPs are commonly used to instantiate business logic — and this is usually embodied in the flow of the code through the procedure or procedures. In this kind of situation simply bench testing the SQL statements does not really test the procedure.
Insert print statements in your Stored Procedure. Another common approach is to sprinkle print statements throughout your procedure. This has also been described as “Sherman set the way back machine to 1980″ or so when print statements were about the only game in town. This approach can actually be very useful, especially during the early stages of development. Each database server tends to have its own way of doing print statements and each has their own idiosyncrasies. For example when using MySQL concat() calls to build up a string to output you have to guard against null values, which turn your entire string to null. For example, the following code can be danagerous:
select someColumn from someTable into myVar where.
concat(’better hope myVar is not null’, myVar);
If the where condition results in no rows being selected then myVar might be null and the output of the concat will also be null. It’s better to use concat_ws(”delimiter”, “text to store”) which handles null values appropriately.
There are two main drawbacks to using print statements in this way. First, the print statements are live during production (unless you guard each one with a conditional flag), meaning that you pay the significant performance penalty for logging all the time.
Second and more serious is that if your stored procedures are invoked from a Java application, the print statements don’t go anywhere. The print statements can only be seen if you execute your Stored Procedures from the command line. What’s the point of log messages that you can’t see?
Develop a rigorous set of return codes. In this approach you define a detailed set of return codes to cover all interesting cases. The implied contract here is that a given specific return code tells you everything you need to know about the execution of the procedure. Theoretically this is a fine approach but in the real production world it tends to fall apart. A return code might tell you what finally went wrong with a procedure but it’s just too easy to imagine needing to know more about how the procedure got to that failure condition.
Put another way, if you get a support call from your most important customer at 3:00 AM do you want to have to a grand total of one return code to tell you what went wrong?

from : www.ddj.com

Stored Procedures are programs that execute within a database server. They are usually written in a database language such as PL/SQL or ANSI SQL:2003 SQL/PSM. (Granted, some database servers do support Java stored procedures, but I don’t examine them here.) There are any number of books for learning to write Stored Procedures – MySQL Stored Procedure Programming, by Guy Harrison, and Teach Yourself PL/SQL in 21 Days,by Jonathan Gennick and Tom Luers, come to mind), but there are a handful of general reasons to write code in a stored procedure:

  • The logic being implemented might be database logic and so a database language is closer to the problem domain than a general purpose language like Java.
  • A stored procedure can be significantly faster than a Java program which might make multiple calls to the database.
  • A stored procedure can be more secure.

Regardless of the reasons for choosing to write a stored procedure, the problem remains of how to debug one. What if you could debug in both development and production at little to no cost to the performance of the Stored Procedures? Traditional debuggers do not generally work with stored procedures which can leave a developer with a fast and broken procedure executing within their database server.

Approaches That Don’t Work

Debug the SQL in your Stored Procedure. This approach works on the assumption the main logic of your Stored Procedures is the actual DDL and DML within the procedure, in other words, the queries, inserts and so on. It assumes that the rest of the Stored Procedures is largely scaffolding to support the database operations. In many cases this is a valid assumption, after all if the Stored Procedure wasn’t manipulating the database you probably wouldn’t have written it as a Stored Procedure.

It goes without saying that regardless of how much non-SQL code you have in your Stored Procedures you need to validate the SQL itself, especially since this level of testing can be relatively straightforward. It can be as simple as starting your database command line tool (or query browser for the gui inclined) and pasting in the guts of your SQL statements to verify correctness. This of course goes beyond simple syntactic correctness, you must validate the semantic correctness as well.

In some cases however it’s not quite that simple, for a couple of classes of reasons. First, your SQL code can (and usually will) rely on variables and parameters that have been defined and/or manipulated by the Stored Procedures. If you have a select statement that stored its results into a variable, and then a later SQL statement that uses that variable, then your “paste the sql into the command line” approach of testing gets a bit harder. You have to insert the one or more statements, execute them, perhaps creating temporary variables along the way, and possibly modify the SQL you are actually trying to test. This happens by degree but you can certainly reach a point where it’s clear that you’re no longer testing the SQL you started with.

The second class of problem with this approach is that often the logic of the Stored Procedures lives in the procedural code of the procedure and not in the SQL statements themselves. SPs are commonly used to instantiate business logic — and this is usually embodied in the flow of the code through the procedure or procedures. In this kind of situation simply bench testing the SQL statements does not really test the procedure.

Insert print statements in your Stored Procedure. Another common approach is to sprinkle print statements throughout your procedure. This has also been described as “Sherman set the way back machine to 1980″ or so when printstatements were about the only game in town. This approach can actually be very useful, especially during the early stages of development. Each database server tends to have its own way of doing print statements and each has their own idiosyncrasies. For example when using MySQL concat() calls to build up a string to output you have to guard against null values, which turn your entire string to null. For example, the following code can be danagerous:

select someColumn from someTable into myVar where.
concat('better hope myVar is not null', myVar);

If the where condition results in no rows being selected then myVar might be null and the output of the concat will also be null. It’s better to useconcat_ws(”delimiter”, “text to store”) which handles null values appropriately.

There are two main drawbacks to using print statements in this way. First, theprint statements are live during production (unless you guard each one with a conditional flag), meaning that you pay the significant performance penalty for logging all the time.

Second and more serious is that if your stored procedures are invoked from a Java application, the print statements don’t go anywhere. The printstatements can only be seen if you execute your Stored Procedures from the command line. What’s the point of log messages that you can’t see?

Develop a rigorous set of return codes. In this approach you define a detailed set of return codes to cover all interesting cases. The implied contract here is that a given specific return code tells you everything you need to know about the execution of the procedure. Theoretically this is a fine approach but in the real production world it tends to fall apart. A return code might tell you what finally went wrong with a procedure but it’s just too easy to imagine needing to know more about how the procedure got to that failure condition.

Put another way, if you get a support call from your most important customer at 3:00 AM do you want to have to a grand total of one return code to tell you what went wrong?

The Proposed Approach

The current approach uses several of MySQL’s special features to create a logging scheme that is both robust and practically free. We create two tables: a temporary log table using the Memory engine and a permanent log table using the MyISAM engine. MySQL supports several storage engines that act as handlers for different table types. MySQL storage engines include both those that handle transaction-safe tables and those that handle non-transaction-safe tables. The memory engine performs all operations in memory and never writes to disk. As such it is very fast, though transient. The MyISAM engine is a non-transactional engine, transactions can include both transactional and non-transactional tables (the non-transactional table simply ignore the transactional commands).

Log messages are inserted into the tmplog table, which is a practically free operation since that table lives in memory. The extremely low cost of this operation means that a developer can be very verbose in their use of logging. Rather than agonize over whether to log something or not, you can simply log at will.

In the (hopefully) usual case where nothing goes wrong, the Stored Procedures does not have to do anything. Temporary tables only exist for the duration of a connection. In the typical J2EE usage pattern, an external request arrives at the system, a connection is retrieved from the connection pool, is used and then returned to the pool. When the connection is returned to the pool the temporary table is effectively dropped — the code does not have to do anything to remove the log messages that where inserted during the successful invocation of the Stored Procedures. In this way the system suffers little to no performance cost for a successful operation.

When the Stored Procedure detects a failure condition it does an INSERT SELECT from the temporary memory table into the permanent MyISAM table. Thus it preserves all log messages that were written to the memory table into the MyISAM table. In this way the system records all of the information it needs but only in the cases where it needs it.

Log4J users can imagine being able to run your production system at DEBUG level for all the failure cases but only pay the overhead of running at WARN level for all of the successful cases — without having to know which cases were which ahead of time.

An important thing to note is the choice of the MyISAM engine for the permanent log table. Remember that rows are typically only written to that table when things are going badly. That would usually result in the current transaction being rolled back — except that we really want the inserts into the log table to succeed! The MyISAM engine is not a transactional engine. This means that even if a transaction is rolled back the inserts into the log table are preserved — which is exactly the desired behavior.

The Code

There are four SPs defined in the debugLogging.sql package. Two SPs help setup the tables to be used, one performs temporary logging and the last copies messages to the permanent table.

This first procedure creates both the temporary and permanant tables. Note the use of the engine specifier to distinguish the two tables. The temporary log contains a single interesting column which was called msg. The permanent table adds an automatic timestamp and a thingID. The assumption is that the logs are written during an operation that creates, destroys, or modifies some object, and that that object has a unique identifier. In the video-on-demand space that I work in, this can be the identifier of a movie being streamed to a customer’s set-top box.

Create Procedure setupLogging()
 BEGIN
     create temporary table if not exists tmplog (msg varchar(512)) engine = memory;
      create table if not exists log (ts timestamp default current_timestamp, thingID bigint,
           msg varchar(512)) engine = myisam;
  END;

This next procedure creates just the temporary log table. We’ve seen cases in the field where the temporary table does not exist at the time that we are needing to insert into it. In that case we have a procedure to recreate the table.

Create Procedure setupTmpLog()
 BEGIN
     create temporary table if not exists tmplog (msg varchar(512)) engine = memory;
  END;

The next procedure is the one that is called the most and performs the actual logging. A message parameter is written to the temporary table. There is a continue handler that creates the temporary table if it does not already exist.

Create Procedure doLog(in logMsg varchar(512))
BEGIN
  Declare continue handler for 1146 -- Table not found
  BEGIN
     call setupTmpLog();
     insert into tmplog values('resetup tmp table');
     insert into tmplog values(logMsg);
  END;

  insert into tmplog values(logMsg);
END;

The last procedure is the one to call when an error is detected within the user’s SP and all of the logging needed to be saved for later analysis. This procedure takes a final message, presumably one saying what the final error condition is. It then inserts all of the rows in the temporary table into the permanent table, setting the timestamp along the way. To handle the situation where the user of the logging system chooses to continue after an error, and then runs into another error we make sure to delete all rows in the temporary table after inserting them into the permenant table.

Create Procedure saveAndLog(in thingId int, in lastMsg varchar(512))
BEGIN
   call dolog(lastMsg);
   insert into log(thingId, msg) (select thingId, msg from tmplog);
   truncate table tmplog;
END;

Sample Use

The following code sample shows a possible usage of the logging procedures. The example is based on the notion of a Stored Procedure that would be called from within another stored procedure. The mission of the inner procedure is to parse a comma separated list of values and insert each value into a cache table for use in a query by the calling procedure. It illustrates the value of being able to log not just the final results but the steps followed along the way since it might be very valuable to know which iteration of the loop contained the failure.

Create Procedure parseAndStoreList(in thingId int,
                                                             in i_list varchar (128),
                                                             out returnCode smallInt)
 BEGIN
    DECLARE v_loopIndex default 0;
    DECLARE Exit Handler for SQLEXCEPTION
    BEGIN
         call saveAndLog(thingId, 'got exception parsing list');    -- save the logs if things go badly
         set returnCode = -1;
    END;

    call dolog(concat_ws('got list:', i_list));   -- say we got to the start
    pase_loop: LOOP
         set v_loopIndex = v_loopIndex + 1;
         call dolog(concat_wc(',', 'at loop iteration ',  v_loopIndex);  -- say we got to nth iteration
         -- actually do the parsing, or whatever
    END LOOOP parse_loop;
    set returnCode = 0;
 END;

Conclusion

The ability to do low- or no-cost logging with Stored Procedures has proven to be an extremely useful technique. It lets you instrument your code with extensive information, which is available at production runtime, but only when needed.

影响MYSQL性能的84点

2009年6月18日 lalfa.shi 没有评论

MySQL is a widely used and fast SQL database server. It is a client/server implementation that consists of a server daemon (mysqld) and many different client programs/libraries.

Here are very useful tips for all mysql DBA’s, Developers these tips are noted from MySQL Camp 2006 suggested by mysql community experts.

1. Kaj (Most Excellent Obvious Facilitator) Index stuff.
2. Ronald Don’t Index Everything
3. Use benchmarking
4. Minimize traffic by fetching only what you need.
1. Paging/chunked data retrieval to limit
2. Don’t use SELECT *
3. Be wary of lots of small quick queries if a longer query can be more efficient
5. Use EXPLAIN to profile the query execution plan
6. Use Slow Query Log (always have it on!)
7. Don’t use DISTINCT when you have or could use GROUP BY
8. Use proper data partitions
1. For Cluster. Start thinking about Cluster *before* you need them
9. Insert performance
1. Batch INSERT and REPLACE
2. Use LOAD DATA instead of INSERT
10. LIMIT m,n may not be as fast as it sounds
11. Don’t use ORDER BY RAND() if you have > ~2K records
12. Use SQL_NO_CACHE when you are SELECTing frequently updated data or large sets of data
13. avoid wildcards at the start of LIKE queries
14. avoid correlated subqueries and in select and where clause (try to avoid in)
15. config params -
16. no calculated comparisons – isolate indexed columns
17. innodb_flush_commit=0 can help slave lag
18. ORDER BY and LIMIT work best with equalities and covered indexes
19. isolate workloads don’t let administrative work interfere with customer performance. (ie backups)
20. use optimistic locking, not pessimistic locking. try to use shared lock, not exclusive lock. share mode vs. FOR UPDATE
21. use row-level instead of table-level locking for OLTP workloads
22. Know your storage engines and what performs best for your needs, know that different ones exist.
1. use MERGE tables ARCHIVE tables for logs
23. Optimize for data types, use consistent data types. Use PROCEDURE ANALYSE() to help determine if you need less
24. separate text/blobs from metadata, don’t put text/blobs in results if you don’t need them
25. if you can, compress text/blobs
26. compress static data
27. don’t back up static data as often
28. derived tables (subqueries in the FROM clause) can be useful for retrieving BLOBs w/out sorting them. (self-join can speed up a query if 1st part finds the IDs and use it to fetch the rest)
29. enable and increase the query and buffer caches if appropriate
30. ALTER TABLE…ORDER BY can take chronological data and re-order it by a different field
31. InnoDB ALWAYS keeps the primary key as part of each index, so do not make the primary key very large, be careful of redundant columns in an index, and this can make the query faster
32. Do not duplicate indexes
33. Utilize different storage engines on master/slave ie, if you need fulltext indexing on a table.
34. BLACKHOLE engine and replication is much faster than FEDERATED tables for things like logs.
35. Design sane query schemas. don’t be afraid of table joins, often they are faster than denormalization
36. Don’t use boolean flags
37. Use a clever key and ORDER BY instead of MAX
38. Keep the database host as clean as possible. Do you really need a windowing system on that server?
39. Utilize the strengths of the OS
40. Hire a MySQL TM Certified DBA
41. Know that there are many consulting companies out there that can help, as well as MySQL’s Professional Services.
42. Config variables & tips:
1. use one of the supplied config files
2. key_buffer, unix cache (leave some RAM free), per-connection variables, innodb memory variables
3. be aware of global vs. per-connection variables
4. check SHOW STATUS and SHOW VARIABLES (GLOBAL|SESSION in 5.0 and up)
5. be aware of swapping esp. with Linux, “swappiness” (bypass OS filecache for innodb data files, innodb_flush_method=O_DIRECT if possible (this is also OS specific))
6. defragment tables, rebuild indexes, do table maintenance
7. If you use innodb_flush_txn_commit=1, use a battery-backed hardware cache write controller
8. more RAM is good so faster disk speed
9. use 64-bit architectures
43. Know when to split a complex query and join smaller ones
44. Debugging sucks, testing rocks!
45. Delete small amounts at a time if you can
46. Archive old data – don’t be a pack-rat! 2 common engines for this are ARCHIVE tables and MERGE tables
47. use INET_ATON and INET_NTOA for IP addresses, not char or varchar
48. make it a habit to REVERSE() email addresses, so you can easily search domains
49. -skip-name-resolve
50. increase myisam_sort_buffer_size to optimize large inserts (this is a per-connection variable)
51. look up memory tuning parameter for on-insert caching
52. increase temp table size in a data warehousing environment (default is 32Mb) so it doesn’t write to disk (also constrained by max_heap_table_size, default 16Mb)
53. Normalize first, and denormalize where appropriate.
54. Databases are not spreadsheets, even though Access really really looks like one. Then again, Access isn’t a real database
55. In 5.1 BOOL/BIT NOT NULL type is 1 bit, in previous versions it’s 1 byte.
56. A NULL data type can take more room to store than NOT NULL
57. Choose appropriate character sets & collations – UTF16 will store each character in 2 bytes, whether it needs it or not, latin1 is faster than UTF8.
58. make similar queries consistent so cache is used
59. Have good SQL query standards
60. Don’t use deprecated features
61. Use Triggers wisely
62. Run in SQL_MODE=STRICT to help identify warnings
63. Turning OR on multiple index fields (<5.0) into UNION may speed things up (with LIMIT), after 5.0 the index_merge should pick stuff up.
64. /tmp dir on battery-backed write cache
65. consider battery-backed RAM for innodb logfiles
66. use min_rows and max_rows to specify approximate data size so space can be pre-allocated and reference points can be calculated.
67. as your data grows, indexing may change (cardinality and selectivity change). Structuring may want to change. Make your schema as modular as your code. Make your code able to scale. Plan and embrace change, and get developers to do the same.
68. pare down cron scripts
69. create a test environment
70. try out a few schemas and storage engines in your test environment before picking one.
71. Use HASH indexing for indexing across columns with similar data prefixes
72. Use myisam_pack_keys for int data
73. Don’t use COUNT * on Innodb tables for every search, do it a few times and/or summary tables, or if you need it for the total # of rows, use SQL_CALC_FOUND_ROWS and SELECT FOUND_ROWS()
74. use -safe-updates for client
75. Redundant data is redundant
76. Use INSERT … ON DUPLICATE KEY update (INSERT IGNORE) to avoid having to SELECT
77. use groupwise maximum instead of subqueries
78. be able to change your schema without ruining functionality of your code
79. source control schema and config files
80. for LVM innodb backups, restore to a different instance of MySQL so Innodb can roll forward
81. use multi_query if appropriate to reduce round-trips
82. partition appropriately
83. partition your database when you have real data
84. segregate tables/databases that benefit from different configuration variables

分类: Database 标签:

render two tbar in one Ext.grid

2009年5月21日 lalfa.shi 1 条评论

edit the extjs example , open the “ext-3.0-rc1.1/examples/grid/grid3.js” file .

we will edit the third grid grid example.

under the tbar line ,we add such code:

listeners : {
  'render' : function() {
      var tbar = new Ext.Toolbar({
        items : [{
            text:'Add Something',
            tooltip:'Add a new row',
            iconCls:'add'
        }, '-', {
            text:'Options',
            tooltip:'Blah blah blah blaht',
            iconCls:'option'
        },'-',{
            text:'Remove Something',
            tooltip:'Remove the selected item',
            iconCls:'remove'
        }]
     });
     tbar.render(this.tbar);   // defaults to appending to the end of the container
  }
},
tbar.render(this.tbar,0);  // position : before of the  container
tbar.render(this.tbar,1);  // position : the end of the container

the refresh the page,the tow tbar under this pic

two-tbar

分类: Other 标签:

Copy that – A new JDK 7 File I/O Example

2009年5月6日 lalfa.shi 没有评论

Copy.java is one of several new samples included in JDK 7 to demonstrate its new API to the file system. If you have any recent snapshot installed then you’ll find these samples in the $JAVA_HOME/sample/nio/file directory.

其中,部分代码值得借鉴,比如对主要函数的处理,也可以了解下JDK7中NIO2:

import java.nio.file.*;
import static java.nio.file.StandardCopyOption.*;
import java.nio.file.attribute.*;
import static java.nio.file.FileVisitResult.*;
import java.io.IOException;
import java.util.*;

/**
 * Sample code that copies files in a similar manner to the cp(1) program.
 */

public class Copy {

    /**
     * Returns {@code true} if okay to overwrite a  file ("cp -i")
     */
    static boolean okayToOverwrite(FileRef file) {
        String answer = System.console().readLine("overwrite %s (yes/no)? ", file);
        return (answer.equalsIgnoreCase("y") || answer.equalsIgnoreCase("yes"));
    }

    /**
     * Copy source file to target location. If {@code prompt} is true then
     * prompt user to overwrite target if it exists. The {@code preserve}
     * parameter determines if file attributes should be copied/preserved.
     */
    static void copyFile(Path source, Path target, boolean prompt, boolean preserve) {
        CopyOption[] options = (preserve) ?
            new CopyOption[] { COPY_ATTRIBUTES, REPLACE_EXISTING } :
            new CopyOption[] { REPLACE_EXISTING };
        if (!prompt || target.notExists() || okayToOverwrite(target)) {
            try {
                source.copyTo(target, options);
            } catch (IOException x) {
                System.err.format("Unable to copy: %s: %s%n", source, x);
            }
        }
    }

    /**
     * A {@code FileVisitor} that copies a file-tree ("cp -r")
     */
    static class TreeCopier implements FileVisitor<Path> {
        private final Path source;
        private final Path target;
        private final boolean prompt;
        private final boolean preserve;

        TreeCopier(Path source, Path target, boolean prompt, boolean preserve) {
            this.source = source;
            this.target = target;
            this.prompt = prompt;
            this.preserve = preserve;
        }

        @Override
        public FileVisitResult preVisitDirectory(Path dir) {
            // before visiting entries in a directory we copy the directory
            // (okay if directory already exists).
            CopyOption[] options = (preserve) ?
                new CopyOption[] { COPY_ATTRIBUTES } : new CopyOption[0];

            Path newdir = target.resolve(source.relativize(dir));
            try {
                dir.copyTo(newdir, options);
            } catch (FileAlreadyExistsException x) {
                // ignore
            } catch (IOException x) {
                System.err.format("Unable to create: %s: %s%n", newdir, x);
                return SKIP_SUBTREE;
            }
            return CONTINUE;
        }

        @Override
        public FileVisitResult preVisitDirectoryFailed(Path dir, IOException exc) {
            System.err.format("Unable to copy: %s: %s%n", dir, exc);
            return CONTINUE;
        }

        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
            if (attrs.isDirectory()) {
                System.err.println("cycle detected: " + file);
            } else {
                copyFile(file, target.resolve(source.relativize(file)),
                         prompt, preserve);
            }
            return CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
            // fix up modification time of directory when done
            if (exc == null && preserve) {
                Path newdir = target.resolve(source.relativize(dir));
                try {
                    BasicFileAttributes attrs = Attributes.readBasicFileAttributes(dir);
                    Attributes.setLastModifiedTime(newdir,
                        attrs.lastModifiedTime(), attrs.resolution());
                } catch (IOException x) {
                    System.err.format("Unable to copy all attributes to: %s: %s%n", newdir, x);
                }
            }
            return CONTINUE;
        }

        @Override
        public FileVisitResult visitFileFailed(Path file, IOException exc) {
            System.err.format("Unable to copy: %s: %s%n", file, exc);
            return CONTINUE;
        }
    }

    static void usage() {
        System.err.println("java Copy [-ip] source... target");
        System.err.println("java Copy -r [-ip] source-dir... target");
        System.exit(-1);
    }

    public static void main(String[] args) throws IOException {
        boolean recursive = false;
        boolean prompt = false;
        boolean preserve = false;

        // process options
        int argi = 0;
        while (argi < args.length) {
            String arg = args[argi];
            if (!arg.startsWith("-"))
                break;
            if (arg.length() < 2)
                usage();
            for (int i=1; i<arg.length(); i++) {
                char c = arg.charAt(i);
                switch (c) {
                    case 'r' : recursive = true; break;
                    case 'i' : prompt = true; break;
                    case 'p' : preserve = true; break;
                    default : usage();
                }
            }
            argi++;
        }

        // remaining arguments are the source files(s) and the target location
        int remaining = args.length - argi;
        if (remaining < 2)
            usage();
        Path[] source = new Path[remaining-1];
        int i=0;
        while (remaining > 1) {
            source[i++] = Paths.get(args[argi++]);
            remaining--;
        }
        Path target = Paths.get(args[argi]);

        // check if target is a directory
        boolean isDir = false;
        try {
            isDir = Attributes.readBasicFileAttributes(target).isDirectory();
        } catch (IOException x) {
            // ignore (probably target does not exist)
        }

        // copy each source file/directory to target
        for (i=0; i<source.length; i++) {
            Path dest = (isDir) ? target.resolve(source[i].getName()) : target;

            if (recursive) {
                // follow links when copying files
                EnumSet<FileVisitOption> opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
                TreeCopier tc = new TreeCopier(source[i], dest, prompt, preserve);
                Files.walkFileTree(source[i], opts, Integer.MAX_VALUE, tc);
            } else {
                // not recursive so source must not be a directory
                try {
                    if (Attributes.readBasicFileAttributes(source[i]).isDirectory()) {
                        System.err.format("%s: is a directory%n", source[i]);
                        continue;
                    }
                } catch (IOException x) {
                    // assume not directory
                }
                copyFile(source[i], dest, prompt, preserve);
            }
        }
    }
}
分类: JAVA 标签: