Preview only show first 10 pages with watermark. For full document please download

Vfabric Sqlfire User's Guide Vmware Vfabric Sqlfire 1.1 Vmware Vfabric Suite 5.3

   EMBED


Share

Transcript

vFabric SQLFire User's Guide VMware vFabric SQLFire 1.1 VMware vFabric Suite 5.3 This document supports the version of each product listed and supports all subsequent versions until the document is replaced by a new edition. To check for more recent editions of this document, see http://www.vmware.com/support/pubs. EN-001171-00 You can find the most up-to-date technical documentation on the VMware Web site at: http://www.vmware.com/support/ The VMware Web site also provides the latest product updates. If you have comments about this documentation, submit your feedback to: [email protected] Copyright © 2013 VMware, Inc. All rights reserved. This product is protected by U.S. and international copyright and intellectual property laws. VMware products are covered by one or more patents listed at http://www.vmware.com/go/patents VMware is a registered trademark or trademark of VMware, Inc. in the United States and/or other jurisdictions. All other marks and names mentioned herein may be trademarks of their respective companies. VMware, Inc. 3401 Hillview Ave. Palo Alto, CA 94304 Contents Part I: About the SQLFire User's Guide....................................................1 Part II: Supported Configurations and System Requirements...............3 Part III: Getting Started with vFabric SQLFire..........................................7 vFabric SQLFire in 15 Minutes.....................................................................................................................8 Chapter 1: Overview of vFabric SQLFire................................................13 Data Flow Diagram.....................................................................................................................................14 GemFire, Apache Derby, and SQL Components........................................................................................14 Chapter 2: Understanding the SQLFire Distributed System.................17 vFabric SQLFire Members..........................................................................................................................17 Servers, Peer Clients, and Server Groups..................................................................................................18 Discovery Mechanisms...............................................................................................................................18 Group Membership Service........................................................................................................................18 Replicated Tables and Partitioned Tables...................................................................................................19 Parallel Execution of Data-Aware Stored Procedures.................................................................................19 Cache Plug-ins for External Data Connections..........................................................................................20 Chapter 3: Installing vFabric SQLFire.....................................................21 Installation Note for vFabric Suite Customers.............................................................................................21 RHEL Only: Install vFabric SQLFire from an RPM.....................................................................................21 Install vFabric SQLFire from a ZIP File.......................................................................................................25 Chapter 4: Activating vFabric SQLFire Licensing.................................27 Understand vFabric SQLFire License Options...........................................................................................27 Choose a License Option Based on Topology............................................................................................28 How vFabric SQLFire Manages Licensing..................................................................................................30 Install and Configure vFabric SQLFire Licenses.........................................................................................31 Verify Your License and Check Your License Usage...................................................................................33 Chapter 5: Upgrading vFabric SQLFire..................................................35 Before You Upgrade....................................................................................................................................35 RHEL: Upgrade vFabric SQLFire from RPM..............................................................................................36 Upgrade vFabric SQLFire from a ZIP File..................................................................................................37 Version Compatibility Rules........................................................................................................................39 Chapter 6: Connect to vFabric SQLFire with JDBC Tools.....................41 iii Chapter 7: Tutorials..................................................................................43 Main Steps..................................................................................................................................................43 Create a SQLFire Cluster...........................................................................................................................43 Connect to the Cluster Using SQLF...........................................................................................................45 Create Replicated Tables and Execute Queries.........................................................................................46 Implement a Partitioning Strategy...............................................................................................................47 Persist Tables to Disk..................................................................................................................................49 Add Servers to the Cluster and Stop Servers.............................................................................................51 Perform Additional Tasks............................................................................................................................52 Chapter 8: vFabric SQLFire Features and Benefits...............................53 Part IV: Managing Your Data in vFabric SQLFire....................................55 Chapter 9: Designing vFabric SQLFire Databases................................57 Design Principles of Scalable, Partition-Aware Databases.........................................................................57 Identify Entity Groups and Partitioning Keys...............................................................................................57 Replicate Code Tables................................................................................................................................58 Dealing with Many-to-Many Relationships..................................................................................................58 Example: Adapting a Database Schema for SQLFire.................................................................................59 Chapter 10: Using Server Groups to Manage Data................................63 Server Groups Overview.............................................................................................................................63 Adding Members to Server Groups............................................................................................................65 Assigning Tables to Server Groups.............................................................................................................66 Chapter 11: Partitioning Tables...............................................................67 How Table Partitioning Works.....................................................................................................................67 Understanding Where Data Is Stored.........................................................................................................68 Failure and Redundancy.............................................................................................................................69 Creating Partitioned Tables.........................................................................................................................70 Rebalancing Partitioned Data on SQLFire Members..................................................................................75 Managing Replication Failures....................................................................................................................76 Chapter 12: Replicating Tables................................................................77 How SQLFire Replicates Tables.................................................................................................................77 Deciding When to Use Replicated Tables...................................................................................................77 Creating Replicated Tables.........................................................................................................................78 Chapter 13: Estimating Memory Requirements.....................................79 Estimating SQLFire Overhead....................................................................................................................79 Viewing Memory Usage in SYS.MEMORYANALYTICS..............................................................................80 Chapter 14: Using Disk Stores to Persist Data......................................85 iv vFabric SQLFire User's Guide Contents Overview of Disk Stores..............................................................................................................................85 Guidelines for Designing Disk Stores.........................................................................................................91 Creating a Disk Store or Using the Default.................................................................................................92 Persist Table Data to a Disk Store...............................................................................................................92 Optimizing Availability and Performance.....................................................................................................93 Starting System with Disk Stores................................................................................................................93 Disk Store Management.............................................................................................................................96 Chapter 15: Exporting and Importing Data with vFabric SQLFire.....105 Using SQLF Commands to Export and Import Data................................................................................105 Using Apache DdlUtils to Import Data......................................................................................................107 Exporting and Importing Data from Text Files...........................................................................................110 Chapter 16: Using Table Functions to Import Data as a SQLFire Tables.113 Overview of SQLFire Table Functions.......................................................................................................113 Example Table Function............................................................................................................................115 Part V: Developing Applications with SQLFire.....................................117 Chapter 17: Starting SQLFire Servers with the FabricServer Interface.119 Starting a Network Server........................................................................................................................120 Chapter 18: Developing Java Clients and Peers..................................123 Connect to a SQLFire Server with the Thin Client JDBC Driver...............................................................123 Start a SQLFire Peer with the Peer Client JDBC Driver...........................................................................126 Chapter 19: Configuring SQLFire as a JDBC Datasource..................129 Using SQLFire with Hibernate..................................................................................................................118 Chapter 20: Storing and Loading JAR Files in SQLFire......................131 Class Loading Overview...........................................................................................................................131 Alternate Methods for Managing JAR Files..............................................................................................133 Chapter 21: Developing ADO.NET Client Applications.......................137 About the ADO.NET Driver.......................................................................................................................137 ADO.NET Driver Classes..........................................................................................................................138 Installing and Using the ADO.NET driver..................................................................................................139 Connecting to SQLFire with the ADO.NET Driver....................................................................................140 Managing Connections.............................................................................................................................140 Executing SQL Commands.......................................................................................................................141 Working with Result Sets..........................................................................................................................141 Storing a Table..........................................................................................................................................142 Storing Multiple Tables..............................................................................................................................143 Specifying Command Parameters with SQLFParameter..........................................................................144 Updating Row Data...................................................................................................................................145 v Adding Rows to a Table............................................................................................................................146 Managing SQLFire Transactions...............................................................................................................147 Performing Batch Updates........................................................................................................................148 Generic Coding with the SQLFire ADO.NET Driver..................................................................................149 Chapter 22: Using SQLFire.NET Designer...........................................153 Installing SQLFire.NET Designer..............................................................................................................153 Connecting to a SQLFire Distributed System...........................................................................................153 Editing Tables............................................................................................................................................154 Chapter 23: Understanding the Data Consistency Model...................155 Data Consistency Concepts.....................................................................................................................155 No Ordering Guarantee for DML in Separate Threads.............................................................................156 Updates on Any Row Are Atomic and Isolated.........................................................................................156 Atomicity for Bulk Updates........................................................................................................................156 Chapter 24: Using Distributed Transactions in Your Applications.....157 Overview of SQLFire Distributed Transactions.........................................................................................157 Sequence of Events for a Distributed Transaction....................................................................................160 SQLFire Transaction Design.....................................................................................................................161 Best Practices for Using Transactions.......................................................................................................161 Transaction Functionality and Limitations.................................................................................................162 Chapter 25: Using Data-Aware Stored Procedures.............................163 Configuring a Procedure...........................................................................................................................163 Configuring a Custom Result Processor...................................................................................................164 Invoking a Procedure................................................................................................................................165 Example JDBC Client...............................................................................................................................166 Chapter 26: Using the Procedure Provider API....................................169 Procedure Parameters..............................................................................................................................169 Populating OUT and INOUT Parameters..................................................................................................170 Populating Result Sets..............................................................................................................................170 Using the and Escape Syntax with Nested Queries......................................................172 Chapter 27: Using the Custom Result Processor API.........................173 Implementing the ProcedureResultProcessor Interface ..........................................................................173 Example Result Processor: MergeSort.....................................................................................................173 Chapter 28: Programming User-Defined Types....................................177 Chapter 29: Using Result Sets and Cursors........................................181 Non-updatable, Forward-Only Result Sets...............................................................................................181 Updatable Result Sets..............................................................................................................................182 Scrollable Insensitive Result Sets.............................................................................................................187 vi vFabric SQLFire User's Guide Contents Result Sets and Autocommit.....................................................................................................................188 Part VI: Caching Data with vFabric SQLFire.........................................189 Chapter 30: SQLFire Cache Strategies.................................................191 Chapter 31: Using a RowLoader to Load Existing Data......................193 How SQLFire Invokes a RowLoader.........................................................................................................193 Implementing the RowLoader Interface....................................................................................................194 Using the JDBCRowLoader Example.......................................................................................................194 Chapter 32: Evicting Table Data from SQLFire.....................................197 How LRU Eviction Works..........................................................................................................................197 Limitations of Eviction...............................................................................................................................197 Eviction in Partitioned Tables....................................................................................................................198 Create a Table with Eviction Settings........................................................................................................198 Chapter 33: Handling DML Events Synchronously.............................201 Writer and Listener Cache Plug-ins..........................................................................................................201 Example Writer Implementation................................................................................................................202 Example Listener Implementation............................................................................................................202 Chapter 34: Handling DML Events Asynchronously..........................203 How the AsyncEventListener Works.........................................................................................................203 Implementation Requirements..................................................................................................................203 Implementing an AsyncEventListener.......................................................................................................204 Chapter 35: Using DBSynchronizer to Apply DML to an RDBMS......209 How DBSynchronizer Works.....................................................................................................................209 Restrictions and Limitations......................................................................................................................210 Configuring DBSynchronizer....................................................................................................................211 Chapter 36:Suppressing Event Callbacks for a vFabric SQLFire Connection.215 Part VII: Deploying vFabric SQLFire......................................................217 Chapter 37: SQLFire Deployment Models............................................219 Embedded Peer-to-Peer Deployment.......................................................................................................220 Client-Server Deployment.........................................................................................................................222 Multi-site Deployment...............................................................................................................................223 Chapter 38: Steps to Plan and Configure a Deployment....................227 Chapter 39: Configuring Discovery Mechanisms................................229 vii Using Locators..........................................................................................................................................229 Configure Multicast Discovery..................................................................................................................231 Chapter 40: Starting and Configuring SQLFire Servers.....................233 Start and Stop SQLFire Servers Using sqlf..............................................................................................233 Specify the Server Working Directory.......................................................................................................234 Specify Client Connection Information......................................................................................................234 Define Server Groups...............................................................................................................................234 Execute SQL When You Start a Server.....................................................................................................235 Using Additional Boot Properties..............................................................................................................235 Chapter 41: Configuring Multi-site (WAN) Deployments.....................237 About Gateways........................................................................................................................................237 About High Availability for WAN Deployments..........................................................................................239 Limitations of Multi-Site Replication..........................................................................................................240 Prerequisites for WAN Replication............................................................................................................241 Steps to Configure a Multi-site Deployment..............................................................................................241 Chapter 42: Configuring Authentication and Authorization...............249 Configuring User Authentication...............................................................................................................249 User Names in Authentication and Authorization ....................................................................................257 Configuring User Authorization.................................................................................................................258 Configuring Network Encryption and Authentication with SSL/TLS..........................................................262 Part VIII: Managing and Monitoring vFabric SQLFire..........................267 Chapter 43: Configuring and Using SQLFire Log Files.......................269 Log Message Format................................................................................................................................269 Severity Levels..........................................................................................................................................269 Using java.util.logging.Logger for Application Log Messages...................................................................270 Using Trace Flags for Advanced Debugging.............................................................................................270 Chapter 44: Querying SQLFire System Tables and Indexes...............273 Getting Information About SQLFire Members..........................................................................................273 Getting Information About User Tables.....................................................................................................274 Chapter 45: Evaluating Query Plans and Query Statistics.................279 Capture a Query Plan for an Individual Statement...................................................................................279 Capture Query Plans for All Statements...................................................................................................280 Example Query Plan Analysis..................................................................................................................280 Query Plan Codes....................................................................................................................................284 Chapter 46: Overriding Optimizer Choices..........................................287 Chapter 47: Evaluating System and Application Performance..........291 viii vFabric SQLFire User's Guide Contents Collecting System Statistics......................................................................................................................291 Collecting Application Statistics................................................................................................................292 Using VSD to Analyze Statistics...............................................................................................................292 Chapter 48: Using Java Management Extensions (JMX)....................303 Using a JMX Manager Node.....................................................................................................................303 Using a vFabric SQLFire JMX Agent........................................................................................................306 Chapter 49: Best Practices for Tuning Performance...........................319 Tune Application Logic..............................................................................................................................319 Reduce Distribution Overhead..................................................................................................................319 Reduce Overhead of Eviction to Disk.......................................................................................................320 Minimize Update Latency for Replicated Tables.......................................................................................320 Tune FabricServers...................................................................................................................................320 Tuning Disk I/O.........................................................................................................................................321 Running SQLFire in Virtualized Environments..........................................................................................322 Chapter 50: Detecting and Handling Network Segmentation ("Split Brain").323 Part IX: vFabric SQLFire Reference......................................................325 Chapter 51: Configuration Properties..................................................327 Chapter 52: JDBC API............................................................................365 Core JDBC Classes, Interfaces, and Methods.........................................................................................365 Mapping java.sql.Types to SQL Types......................................................................................................370 JDBC Escape Syntax ..............................................................................................................................371 Chapter 53: sqlf Launcher Commands................................................379 sqlf backup................................................................................................................................................381 sqlf compact-all-disk-stores......................................................................................................................383 sqlf compact-disk-store.............................................................................................................................384 sqlf encrypt-password...............................................................................................................................385 sqlf install-jar.............................................................................................................................................387 sqlf list-missing-disk-stores.......................................................................................................................390 sqlf locator................................................................................................................................................391 sqlf Logging Support.................................................................................................................................396 sqlf merge-logs.........................................................................................................................................396 sqlf remove-jar..........................................................................................................................................397 sqlf replace-jar..........................................................................................................................................399 sqlf revoke-missing-disk-store...................................................................................................................401 sqlf run......................................................................................................................................................403 sqlf server.................................................................................................................................................405 sqlf show-disk-store-metadata..................................................................................................................416 sqlf shut-down-all......................................................................................................................................417 ix sqlf sqlf sqlf sqlf sqlf sqlf sqlf sqlf sqlf sqlf stats....................................................................................................................................................418 upgrade-disk-store.............................................................................................................................422 validate-disk-store..............................................................................................................................423 version................................................................................................................................................423 write-data-dtd-to-file...........................................................................................................................424 write-data-to-db..................................................................................................................................426 write-data-to-xml................................................................................................................................431 write-schema-to-db............................................................................................................................435 write-schema-to-sql............................................................................................................................439 write-schema-to-xml...........................................................................................................................443 Chapter 54: sqlf Interactive Commands...............................................449 absolute ...................................................................................................................................................449 after last ...................................................................................................................................................450 async .......................................................................................................................................................451 autocommit ..............................................................................................................................................451 before first ................................................................................................................................................452 close ........................................................................................................................................................452 commit .....................................................................................................................................................453 connect ....................................................................................................................................................453 connect client ...........................................................................................................................................454 connect peer ............................................................................................................................................455 describe ...................................................................................................................................................455 disconnect ................................................................................................................................................456 driver ........................................................................................................................................................457 elapsedtime .............................................................................................................................................457 execute ....................................................................................................................................................458 exit ...........................................................................................................................................................459 first............................................................................................................................................................460 get scroll insensitive cursor.......................................................................................................................460 GetCurrentRowNumber ...........................................................................................................................462 help ..........................................................................................................................................................462 last ...........................................................................................................................................................463 LocalizedDisplay.......................................................................................................................................463 MaximumDisplayWidth.............................................................................................................................464 next...........................................................................................................................................................465 prepare ....................................................................................................................................................465 previous....................................................................................................................................................466 protocol.....................................................................................................................................................467 relative......................................................................................................................................................468 remove......................................................................................................................................................468 rollback......................................................................................................................................................469 run.............................................................................................................................................................470 set connection...........................................................................................................................................471 show..........................................................................................................................................................471 wait for......................................................................................................................................................475 x vFabric SQLFire User's Guide Contents Chapter 55: SQLFire API........................................................................477 CredentialInitializer...................................................................................................................................478 UserAuthenticator.....................................................................................................................................478 Procedure Implementation Interfaces.......................................................................................................478 Procedure Result Processor Interfaces....................................................................................................480 Chapter 56: SQL Language Reference.................................................485 Keywords and Identifiers...........................................................................................................................485 SQL Statements.......................................................................................................................................486 SQL Queries.............................................................................................................................................546 SQL Clauses.............................................................................................................................................547 SQL Expressions......................................................................................................................................552 JOIN Operations.......................................................................................................................................565 Built-in Functions......................................................................................................................................567 Built-in System Procedures......................................................................................................................609 Data Types................................................................................................................................................638 SQL Standards Conformance...................................................................................................................649 Chapter 57: System Tables.....................................................................669 ASYNCEVENTLISTENERS.....................................................................................................................669 GATEWAYRECEIVERS............................................................................................................................670 GATEWAYSENDERS...............................................................................................................................671 INDEXES..................................................................................................................................................673 JARS.........................................................................................................................................................673 MEMBERS................................................................................................................................................674 MEMORYANALYTICS...............................................................................................................................675 STATEMENTPLANS.................................................................................................................................676 SYSALIASES............................................................................................................................................677 SYSCHECKS............................................................................................................................................678 SYSCOLPERMS......................................................................................................................................678 SYSCOLUMNS.........................................................................................................................................680 SYSCONGLOMERATES..........................................................................................................................681 SYSCONSTRAINTS.................................................................................................................................682 SYSDEPENDS.........................................................................................................................................682 SYSDISKSTORES....................................................................................................................................683 SYSFILES.................................................................................................................................................684 SYSFOREIGNKEYS.................................................................................................................................684 SYSKEYS.................................................................................................................................................685 SYSROLES...............................................................................................................................................685 SYSROUTINEPERMS..............................................................................................................................687 SYSSCHEMAS.........................................................................................................................................687 SYSSTATEMENTS...................................................................................................................................688 SYSSTATISTICS.......................................................................................................................................688 SYSTABLEPERMS...................................................................................................................................689 SYSTABLES.............................................................................................................................................691 xi SYSTRIGGERS........................................................................................................................................693 SYSVIEWS...............................................................................................................................................694 Chapter 58: Exception Messages and SQL States..............................695 Chapter 59: ADO.NET Driver Reference...............................................743 SQLFire Data Types in ADO.NET.............................................................................................................743 VMware.Data.SQLFire.BatchUpdateException........................................................................................743 VMWare.Data.SQLFire.SQLFClientConnection.......................................................................................743 VMware.Data.SQLFire.SQLFCommand...................................................................................................748 VMware.Data.SQLFire.SQLFCommandBuilder........................................................................................754 VMware.Data.SQLFire.SQLFType............................................................................................................754 VMware.Data.SQLFire.SQLFDataAdapter...............................................................................................755 VMware.Data.SQLFire.SQLFDataReader................................................................................................757 VMware.Data.SQLFire.SQLFException....................................................................................................759 VMware.Data.SQLFire.SQLFParameter...................................................................................................760 VMware.Data.SQLFire.SQLFParameterCollection...................................................................................760 VMware.Data.SQLFire.SQLFTransaction.................................................................................................761 Chapter 60: vFabric SQLFire Limitations.............................................765 SQL Language Limitations.......................................................................................................................765 ADO.NET Driver Limitations.....................................................................................................................773 Part X: Troubleshooting Common Problems.......................................775 Part XI: vFabric SQLFire Glossary........................................................779 xii vFabric SQLFire User's Guide Part 1 About the SQLFire User's Guide Revised February 18, 2014. The SQLFire User's Guide provides step-by-step procedures for installing, configuring, managing, and developing applications with VMware® vFabric™ SQLFire. The guide also provides a complete reference for the SQLFire tools, supported SQL statements, and APIs. Note: All documentation for Pivotal SQLFire 1.1.2 and later is available at http://docs.gopivotal.com/sqlfire/index.html. Intended Audience The SQLFire User's Guide is intended for anyone who wants to install or deploy SQLFire, and for developers who want to program applications that access a SQLFire system and/or implement SQLFire APIs. The guide assumes that you are familiar with SQL databases and database terminology, and that you have experience in developing database applications using Java or .NET technologies. 1 Part 2 Supported Configurations and System Requirements Before installing vFabric SQLFire, make sure your system meets the minimum system requirements for installing and running the product. • Supported Configurations on page 3 • Host Machine Requirements on page 4 • Increase Unicast Buffer Size on Linux Platforms on page 4 • Disable SYN Cookies on Linux Platforms on page 4 • Client Requirements on page 5 Supported Configurations The following table shows all supported configurations for vFabric SQLFire. These include Supported Configurations and System Requirements for vFabric Suite. Note: The tables indicate whether the supported configuration is for production or development. Generally, production support means you can run your production application on the platform; developer support means you can develop on the platform but you should not run your production application on it. Operating System Processor Architecture JVM Production or Developer Support Red Hat EL 5 x86 (64bit and 32 bit) Java SE 6, update 0_26 Production Red Hat EL 6 x86 (64bit and 32 bit) Java SE 6, update 0_26 Production Windows Server 2003 R2 SP2 Professional or Enterprise* x86 (64bit and 32 bit) Java SE 6, update 0_26 Production Windows Server 2008 R2 Standard* x8 (64bit and 32 bit) Java SE 6, update 0_26 Production Windows 7 SP1 x8 (64bit and 32 bit) Professional or Enterprise* Java SE 6, update 0_26 Developer Windows XP x86 (64 bit) Java SE 6 Developer Ubuntu 10.04 x86 (64 bit) Java SE 6 Developer 3 *The Microsoft Loopback Adapter is not supported. Note: The SQLFire product download does not include Java; you must download and install a supported JDK for your system. Host Machine Requirements Requirements for each host: • A supported Java SE installation. • File system that supports long file names. • Adequate per-user quota of file handles (ulimit for Linux) • TCP/IP. • System clock set to the correct time. • For each Linux host, the hostname and host files must be properly configured. See the system manpages for hostname and hosts. • Time synchronization service such as Network Time Protocol (NTP). Note: For troubleshooting, you must run a time synchronization service on all hosts. Synchronized time stamps allow you to merge log messages from different hosts, for an accurate chronological history of a distributed run. Increase Unicast Buffer Size on Linux Platforms On Linux platforms, execute the following commands as the root user to increase the unicast buffer size: 1. Edit the /etc/sysctl.conf file to include the following lines: net.core.rmem_max=1048576 net.core.wmem_max=1048576 2. Reload sysctl.conf: sysctl -p Disable SYN Cookies on Linux Platforms Many default Linux installations use SYN cookies to protect the system against malicious attacks that flood TCP SYN packets. The use of SYN cookies dramatically reduces network bandwidth, and can be triggered by a running SQLFire distributed system. If your SQLFire distributed system is otherwise protected against such attacks, disable SYN cookies to ensure that SQLFire network throughput is not affected. To disable SYN cookies permanently: 1. Edit the /etc/sysctl.conf file to include the following line: net.ipv4.tcp_syncookies = 0 Setting this value to zero disables SYN cookies. 2. Reload sysctl.conf: sysctl -p 4 vFabric SQLFire User's Guide Client Requirements SQLFire supports two JDBC drivers: a thin client JDBC driver and a peer JDBC driver. SQLFire server instances and the peer driver are supported only with Java SE 6. You can download Java from http://www.oracle.com/technetwork/java/javase/downloads/index.htm. SQLFire provides a managed ADO.NET driver that you can use for developing non-Java client applications. The ADO.NET driver uses IKVM technology to translate SQLFire JDBC core libraries to .NET MSIL. The ADO.NET driver is supported for applications built using the Microsoft .NET 2.0 SP1 or higher framework. 5 Part 3 Getting Started with vFabric SQLFire Getting Started with vFabric SQLFire provides step-by-step procedures for installing, configuring, and using VMware® vFabric™ SQLFire. The guide also explains main concepts and provides tutorials to help you quickly begin using SQLFire. Topics: • • • • • • • • • vFabric SQLFire in 15 Minutes Overview of vFabric SQLFire Understanding the SQLFire Distributed System Installing vFabric SQLFire Activating vFabric SQLFire Licensing Upgrading vFabric SQLFire Connect to vFabric SQLFire with JDBC Tools Tutorials vFabric SQLFire Features and Benefits 7 vFabric SQLFire in 15 Minutes Need a quick introduction to vFabric SQLFire? Take this 15-minute tour to try out the basic features and functionality. The vFabric SQLFire tutorials expand on these concepts, and demonstrate additional product features. See Tutorials on page 43. 1. Download the latest SQLFire 1.1 ZIP file distribution from the download page: https://my.vmware.com/web/vmware/info/slug/application_platform/vmware_vfabric_sqlfire/1_0. Save the downloaded file in your home directory. 2. Install SQLFire 1.1 by uncompressing the ZIP file: $ cd ~ $ unzip vFabric_SQLFire_11_bNNNNN.zip Substitute the exact filename that you downloaded. This installs SQLFire in a new vFabric_SQLFire_11_b NNNNN subdirectory in your home directory, where NNNNN is the specific SQLFire build number that you downloaded. 3. If you have not already done so, download and install Java. For a list of Java versions supported with this release of vFabric SQLFire, see Supported Configurations and System Requirements on page 3. 4. Set your PATH environment variable to include the bin subdirectory of the vFabric SQLFire directory. For example: $ export PATH=$PATH:/home/username/vFabric_SQLFire_11_bNNNNN/bin 5. Change to the SQLFire installation quickstart directory, and create three new directories for the locator and two servers that will make up the SQLFire distributed system: $ cd ~/vFabric_SQLFire_11_bNNNNN/quickstart $ mkdir locator1 server1 server2 6. Start the locator: $ sqlf locator start -peer-discovery-address=localhost -dir=locator1 Starting network server for SQLFire Locator at address localhost/127.0.0.1[1527] SQLFire Locator pid: 8787 status: running Logs generated in /home/yozie/vFabric_SQLFire_11_bNNNNN/quickstart/locator1/sqlflocator.log This command starts a default locator that accepts connections on the localhost address. The default port of 10334 is used for communication with other members of the distributed system. (You can double-check that this port is used by examining the locator1/sqlflocator.log file.) All new members of the distributed system must specify this locator's address and peer discovery port, localhost[10334], in order to join the system. The default port of 1527 is used for client connections to the distributed system. 7. Start both servers: $ sqlf server start -locators=localhost[10334] -bind-address=localhost -client-port=1528 -dir=server1 $ sqlf server start -locators=localhost[10334] -bind-address=localhost -client-port=1529 -dir=server2 Starting SQLFire Server using locators for peer discovery: localhost[10334] Starting network server for SQLFire Server at address localhost/127.0.0.1[1528] 8 vFabric SQLFire User's Guide SQLFire Server pid: 8897 status: running Logs generated in /home/yozie/vFabric_SQLFire_11_bNNNNN/quickstart/server1/sqlfserver.log Starting SQLFire Server using locators for peer discovery: localhost[10334] Starting network server for SQLFire Server at address localhost/127.0.0.1[1529] SQLFire Server pid: 9003 status: running Logs generated in /home/yozie/vFabric_SQLFire_11_bNNNNN/quickstart/server2/sqlfserver.log Both servers also bind to the localhost address. They must specify unique client ports in order to avoid conflicts with the locator's default client port. As an alternative, they could disable the network server entirely by specifying -run-netserver=false, and all clients would need to connect through the locator. 8. Before going any further, check to make sure that you're in the SQLFire quickstart subdirectory. You'll need to run the script files in this directory later in the tutorial, and you must execute those scripts from within the quickstart directory: $ cd ~/vFabric_SQLFire_11_bNNNNN/quickstart 9. Connect to the distributed system as a thin client, and display information about the system members: $ sqlf sqlf> connect client 'localhost:1527'; 10. Now that you're connected to the system, run a simple query to display information about the SQLFire system members: sqlf> select id, kind, netservers from sys.members; ID |KIND |NETSERVERS -----------------------------------------------------------------------------localhost(17355):1374 |locator(normal) |localhost/127.0.0.1[1527] localhost(17535):52946 |datastore(normal)|localhost/127.0.0.1[1529] localhost(17438):1230 |datastore(normal)|localhost/127.0.0.1[1528] 3 rows selected By default, SQLFire servers are started as datastores, so that they can host database schemas. In this cluster, you can connect as a client to any member by specifying localhost with the unique port number of the member (the one specified in the NETSERVERS column). However, connecting to the locator provides basic load balancing by routing the connection request to an available server member. 11. Create a simple table and insert a few rows: sqlf> create table quicktable (id int generated always as identity, item char(25)); 0 rows inserted/updated/deleted sqlf> insert into quicktable values (default, 'widget'); 1 row inserted/updated/deleted sqlf> insert into quicktable values (default, 'gadget'); 1 row inserted/updated/deleted sqlf> select * from quicktable; ID |ITEM ------------------------------------2 |gadget 1 |widget 2 rows selected 9 12. By default, SQLFire replicates new tables that you create onto data store members. You can validate this using the query: sqlf> select tablename, datapolicy from sys.systables where tablename='QUICKTABLE'; TABLENAME |DATAPOLICY ----------------------------------------------------------------------------QUICKTABLE |REPLICATE 1 row selected 13. Execute two SQL scripts to generate a schema that has both replicated and partitioned tables, and then load the schema with data: sqlf> run 'create_colocated_schema.sql'; sqlf> run 'loadTables.sql'; You see numerous messages as various SQL commands are executed. The first script creates both replicated and partitioned tables, as you can see using the query: sqlf> select tablename, datapolicy from sys.systables where tableschemaname='APP'; TABLENAME |DATAPOLICY -----------------------------------------------------------------------------FLIGHTS_HISTORY |PARTITION FLIGHTAVAILABILITY |PARTITION FLIGHTS |PARTITION MAPS |REPLICATE CITIES |REPLICATE COUNTRIES |REPLICATE AIRLINES |REPLICATE QUICKTABLE |REPLICATE 8 rows selected 14. To observe a benefit of table partitioning, look at a query plan that involves one of the partitioned tables. Use the EXPLAIN command with a query to generate a query execution plan: sqlf> explain select * from flights; The EXPLAIN command stores the query execution plan for the statement in STATEMENTPLANS system table. 10 vFabric SQLFire User's Guide 15. To view the details of the query plan, disconnect as a thin client from the distributed system, and then reconnect as a peer client. A peer client participates as a member of the SQLFire distributed system and can coordinate queries, but it does not host any actual data. Execute these commands: sqlf> disconnect; sqlf> connect peer 'host-data=false;locators=localhost[10334]'; You can see that your peer client connection introduces a new member to the distributed system: sqlf> select id, kind, netservers from sys.members; ID |KIND |NETSERVERS -----------------------------------------------------------------------------localhost(17355):1374 |locator(normal) |localhost/127.0.0.1[1527] localhost(17438):1230 |datastore(normal)|localhost/127.0.0.1[1528] localhost(17535):52946 |datastore(normal)|localhost/127.0.0.1[1529] 10.0.1.18(17894):22695 |accessor(normal) | 4 rows selected The term accessor indicates that the member only accesses data, but does not store data for the distributed system. 16. To view the query execution plan that you generated earlier, query the SYS.STATEMENTPLANS table to view the statement ID (STMT_ID), then use EXPLAIN again with the ID to view the plan: sqlf> select stmt_id, stmt_text from sys.statementplans; STMT_ID |STMT_TEXT ------------------------------------------------------------------------------00000001-ffff-ffff-ffff-00020000004c| select * from flights 1 row selected sqlf> explain '00000001-ffff-ffff-ffff-00020000004c'; member localhost(17438):1230 begin_execution 2013-02-27 15:33:30.759 end_execution 2013-02-27 15:33:30.779 QUERY-RECEIVE execute_time 19.440818 ms member_node localhost(17535):52946 RESULT-SEND execute_time 0.130708 ms member_node localhost(17535):52946 RESULT-HOLDER execute_time 10.600616 ms returned_rows 275 no_opens 1 TABLESCAN (100.00%) execute_time 3.250588 ms returned_rows 275 no_opens 1 scan_qualifiers None scanned_object APP.FLIGHTS scan_type HEAP member localhost(17535):52946 begin_execution 2013-02-27 15:33:30.758 end_execution 2013-02-27 15:33:30.89 QUERY-SCATTER execute_time 13.358717 ms member_node localhost(17438):1230,localhost(17535):52946 QUERY-SEND execute_time 3.345079 ms member_node localhost(17438):1230 QUERY-SEND execute_time 1.140207 ms member_node localhost(17535):52946 RESULT-RECEIVE execute_time 0.008155 ms member_node localhost(17535):52946 RESULT-RECEIVE execute_time 1.4887 ms member_node localhost(17438):1230 SEQUENTIAL-ITERATION (35.23%) execute_time 10.463731 ms 11 returned_rows 542 no_opens 1 RESULT-HOLDER execute_time 0.490328 ms returned_rows 267 no_opens 1 member_node localhost(17535):52946 RESULT-HOLDER execute_time 1.65846 ms returned_rows 275 no_opens 1 member_node localhost(17438):1230 DISTRIBUTION-END (64.76%) execute_time 19.233818 ms returned_rows 542 Local plan: member localhost(17535):52946 begin_execution 2013-02-27 15:33:30.762 end_execution 2013-02-27 15:33:30.842 TABLESCAN (100.00%) execute_time 3.297607 ms returned_rows 267 no_opens 1 scan_qualifiers None scanned_object APP.FLIGHTS scan_type HEAP Note: The generated statement ID may be different on your system. Copy the exact ID from the output of the SELECT statement and paste it into the second EXPLAIN statement. The plan describes exactly how SQLFire performed the query. Note the two QUERY-SEND entries. These entries indicate that the results for the query were obtained from each of the two data store members in the distributed system. Because the FLIGHTS table was created as a partitioned table, new rows that are added to the table are uniquely assigned to partitions based on the partitioning key (in this case, the key is the FLIGHT_ID column). Partitions are then placed on data stores, which can process their portion of the data independently when queries are performed against the table. Results from multiple data stores are then merged on a single query coordinator member to provide the final result set. 17. Either continue executing queries against the sample database, or shut down the SQLFire distributed system. To shut down all members of the system, first use the shut-down-all command to stop data stores and accessors. Then shut down any remaining locators: sqlf> quit; $ sqlf shut-down-all -locators=localhost[10334] Connecting to distributed system: locators=localhost[10334] Successfully shut down 2 members $ sqlf locator stop -dir=locator1 The SQLFire Locator has stopped. 18. To continue learning about vFabric SQLFire, read or work through the remaining Tutorials on page 43. 12 vFabric SQLFire User's Guide Chapter 1 Overview of vFabric SQLFire vFabric SQLFire is a memory-optimized, distributed database management system designed for applications that have demanding scalability and availability requirements. Applications can manage database tables entirely in memory, or they can persist tables to disk to reload the data after restarting the system. A SQLFire distributed system can be easily scaled out using commodity hardware. 13 Getting Started with vFabric SQLFire Data Flow Diagram GemFire, Apache Derby, and SQL Components vFabric SQLFire incorporates core vFabric GemFire technology and Apache Derby RDBMS components to provide a high-performance, distributed database management system. SQLFire extends standard SQL statements where necessary for creating and managing tables and configuring the SQLFire system. The sections that follow document how SQLFire utilizes the GemFire and Derby component functionality. vFabric GemFire Technology vFabric SQLFire incorporates the following VMware vFabric GemFire technology: • Reliable data distribution • High performance replication and partitioning • Caching framework • Parallel 'data-aware' application behavior routing 14 vFabric SQLFire User's Guide Overview of vFabric SQLFire The SQLFire community site provides a comparison of SQLFire to other data management systems, such as vFabric GemFire. Apache Derby RDBMS Components SQLFire integrates vFabric GemFire functionality with several components of the Apache Derby relational database management system (RDBMS): • JDBC driver. SQLFire supports a native, high performant JDBC driver (peer driver) and a thin JDBC driver. The peer driver is based on the Derby embedded driver and JDBC 4.0 interfaces, but all communication with SQLFire servers is implemented through the vFabric GemFire distribution layer. • Query engine. SQLFire uses Derby to parse the SQL queries and generate parse trees. SQLFire injects its own logic for intermediate plan creation and distributes the plan to data stores in the cluster. SQLFire also capitalizes on some aspects of the built-in optimizer in Derby to generate query plans. The query execution itself uses memory-based indexes and custom storage data structures. When query execution requires distribution, SQLFire uses a custom algorithm to execute the query in parallel on multiple data stores. • Network server. SQLFire servers embed the Derby network server for connectivity from thin JDBC and ADO.NET clients. The communication protocol is based on the DRDA standard that is used by in IBM DB2 drivers. SQL Extensions vFabric SQLFire modifies and extends the query engine and SQL interface to provide support for partitioned and replicated tables, data-aware procedures, data persistence, data eviction, and other features unique to the distributed SQLFire architecture. SQLFire also adds SQL commands, stored procedures, system tables, and functions to help easily manage features of the distributed system, such as persistent disk stores, listeners, and locators. 15 Chapter 2 Understanding the SQLFire Distributed System A SQLFire deployment consists of distributed member processes that connect to each other to form a peer-to-peer network, also known as a distributed system or SQLFire cluster. The sections that follow explain the interactions of main system components and processes. Tutorials on page 43 help you get started configuring and using a SQLFire distributed system. vFabric SQLFire Members Member processes form a single, logical system, and each member has single-hop access to any other member, with single-hop or no-hop access to data. A SQLFire member is an instance of the SQLFire code that runs in a JVM. A SQLFire member can optionally host data, provide network server functionality for client connections, and provide location services for the distributed system. A SQLFire distributed system is dynamic, and members can be added or removed at any time. The SQLFire implementation guarantees a consistent view of the distributed system to ensure that data consistency and data integrity are not compromised. Most SQLFire members are configured to host data, and are referred to as data stores. Members that are configured to not host data are referred to as accessors. Both data stores and accessors can execute the DDL and DML commands that SQLFire supports. Data stores provide single-hop or no-hop access to data stored that is stored on members of the distributed system. Accessors provide single-hop access to data stores in the distributed system. Data stores and accessors are licensed separately. A third type of member, the standalone locator, does not host data and does not support DDL and DML statements on user-defined tables. You use locators to discover members of the SQLFire cluster. A SQLFire agent is an optional distributed system member that provides access to JMX MBeans for monitoring and managing SQLFire. For more information, see: • Starting and Configuring SQLFire Servers on page 233 • Using Locators on page 229 • Start a SQLFire Peer with the Peer Client JDBC Driver on page 126 • Using a vFabric SQLFire JMX Agent on page 306 17 Getting Started with vFabric SQLFire Servers, Peer Clients, and Server Groups A SQLFire server is a process that hosts data and is a member of a peer-to-peer distributed system. SQLFire servers run in Java Virtual Machines (JVMs). You start a SQLFire server using the sqlf tool from a command prompt or terminal window. sqlf launches servers as standalone processes that are akin to database servers. The servers can accept TCP connections from thin clients, authenticate credentials, manage sessions, delegate work to a thread pool for SQL processing, and so forth. A peer client, also known as an embedded client, is a SQLFire-aware JDBC client that connects to the distributed system using the JDBC peer driver. Peer clients are always connected to the distributed system, and they have single-hop access to data. A peer client can be configured as a pure client (referred to as an accessor member) or as a client that also hosts data (a data store). Both JDBC peer client processes and server processes are peer members of the distributed system. The members discover each other dynamically through a built-in multicast based discovery mechanism or by using a locator service when TCP discovery is more desirable. Note: In addition to peer client members that participate in a cluster, SQLFire servers support thin client connections from JDBC and ADO.NET thin client drivers. See Developing Java Clients and Peers on page 123 and Developing ADO.NET Client Applications on page 137. SQLFire servers and peer clients that host data (when the host-data property is set to true) are automatically part of the default server group. A server group is a logical grouping of SQLFire server and peer client members that defines the data stores that should host data for table. When any SQLFire object is created, such as a table, in the CREATE TABLE statement you can specify the server group name where the table will be hosted. If no group is specified, the table is hosted in the default server group. Using Server Groups to Manage Data on page 63 provides additional information. For more information, see: • Starting and Configuring SQLFire Servers on page 233 • Using Locators on page 229 • Start a SQLFire Peer with the Peer Client JDBC Driver on page 126 • Using Server Groups to Manage Data on page 63 Discovery Mechanisms A peer member (a server or peer client process) announces itself to the distributed system using one of two mechanisms. SQLFire provides these discovery mechanisms: • Locator (TCP/IP). A locator service maintains a registry of all peer members in the distributed system at any given moment. A locator is typically started as a separate process (with redundancy), but you can also embed a locator in any peer member, such as a SQLFire server. The locator opens a TCP port through which all new members connect to get initial membership information. • UDP/IP Multicast. Members can optionally use a multicast address to broadcast their presence and receive membership notification information. Configuring Discovery Mechanisms on page 229 provides more information. Group Membership Service The Group Membership Service (GMS) uses self-defined system membership. Processes can join or leave the distributed system at any time. The GMS communicates this information to every other member in the system, 18 vFabric SQLFire User's Guide Understanding the SQLFire Distributed System with certain consistency guarantees. Each member in the group participates in membership decisions, which ensures that either all members see a new member or no members see it. The membership coordinator, a key component of the GMS, handles "join" and "leave" requests, and also handles members that are suspected of having left the system. The system automatically elects the oldest member of the distributed system to act as the coordinator, and it elects a new one if the member fails or is unreachable. The coordinator's basic purpose is to relay the current membership view to each member of the distributed system and to ensure the consistency of the view at all times. Because the SQLFire distributed system is dynamic, you can add or remove members in a very short time period. This makes it easy to reconfigure the system to handle added demand (load).The GMS permits the distributed system to progress under conditions in which a statically-defined membership system could not. A static model defines members by host and identity, which makes it difficult to add or remove members in an active distributed system. The system would have to shut down partially or completely to expand or contract the number of members that participate in the system. For more information, see: • Start and Stop SQLFire Servers Using sqlf on page 233 • Connect to a Distributed System Using Locators on page 231 • Rebalancing Partitioned Data on SQLFire Members on page 75 Replicated Tables and Partitioned Tables Tables in SQLFire can be partitioned or replicated. A replicated table keeps a copy of its entire data set locally on every SQLFire server in its server group. A partitioned table manages large volumes of data by partitioning it into manageable chunks and distributing those chunks across all members in the table's server group. By default, all tables are replicated unless you specify partitioning in the CREATE TABLE statement. The schema information for all SQLFire objects is visible at all times to all peer members of the distributed system including peer clients, but excluding standalone locators. Partitioning Tables on page 67 and Replicating Tables on page 77 provide more information. Parallel Execution of Data-Aware Stored Procedures In a traditional relational database, stored procedures are application routines that are stored as part of the data dictionary and executed on the database system itself. Stored procedures generally offer high performance because they execute in close proximity to data required by the application logic. SQLFire extends this basic stored procedure capability to support parallel execution of application logic on table data that is partitioned across many peers. SQLFire applications can execute stored procedures on specific data hosts, in parallel on all the members of a server group, or can target specific members based on the data requirements for the procedure. Essentially, application behavior that is encapsulated in stored procedures is moved to the process that hosts the associated data set, and it is executed there. If the required data set is spread across multiple partitions, the procedure is executed in parallel on the partition members. Results are streamed to a coordinating member and aggregated for the client invoking the procedure. For example, consider an 'Order' table that is partitioned by its 'customer_id', and an application wanting to execute an expensive 'credit check' for several customers. Assume the credit test requires iteration over all the order history. You can parallelize the execution on all members that manage data for these customers and stream the results to the client. All order history required by each execution is locally available in-process. // typical procedure call CallableStatement callableStmt = connection.prepareCall("{CALL order_credit_check(?) "); callableStmt.setArray(1, ); 19 Getting Started with vFabric SQLFire // SQLFire data-aware procedure invocation CallableStatement callableStmt = connection.prepareCall("{CALL order_credit_check() " + "ON TABLE Orders WHERE customerID IN (?)}"); callableStmt.setArray(1, ); // order_credit_check will be executed in parallel on all members where the orders // corresponding to the customerIDs are managed For more information, see: • Using Data-Aware Stored Procedures on page 163 • Using the Procedure Provider API on page 169 • Using the Custom Result Processor API on page 173 Cache Plug-ins for External Data Connections SQLFire is commonly used as a distributed SQL cache in an embedded (peer client) or client-server configuration. It provides a plug-in framework to connect the cache to external data sources such as another relational database. Several cache plug-ins are supported: • Reading from Backend on a Miss ("read through") When SQLFire is used as a cache, applications can configure a SQL RowLoader that is triggered to load the data from a backend repository on a miss in SQLFire. When an incoming query request for a uniquely identified row cannot be satisfied by the distributed cache, the loader is invoked to retrieve the data from an external source. SQLFire locks the associated row and prevents concurrent readers trying to fetch the same row from bombarding the backend database. Note: When SQLFire is used as a "pure" cache (that is, some or all tables are configured with LRU eviction, and only the actively used subset of data is cached in SQLFire), queries on these tables can be based only on the primary key. Only primary key-based queries invoke a configured loader. Any other query potentially could produce inconsistent results from the cache. See Using a RowLoader to Load Existing Data on page 193. • Synchronous Write Back to Backend ("write through") When data is strictly managed in memory, even with replication, a failure of the entire cluster means loss of data. With synchronous write-through, all changes can be synchronously written to the backend repository before the cache is changed. If and only if the write-through succeeds, the data becomes visible in the cache. You configure synchronous write-through with a SQLFire "cache writer". See Handling DML Events Synchronously on page 201. • Asynchronous Write Back to Backend ("write behind") If synchronous writes to the backend are too costly, the application can configure the use of a "write behind cache listener". SQLFire supports several options for how the events are queued, batched, and written to the database of record. It is designed for very high reliability and handles many failure conditions. Persistent queues ensure writes even when the backend database is temporarily unavailable. You can order event delivery or batch it based on a time interval. You can also conflate a certain number of rows and continuous updates to a single update, to reduce the load on the backend database of an 'update heavy' system. See Handling DML Events Asynchronously on page 203. 20 vFabric SQLFire User's Guide Chapter 3 Installing vFabric SQLFire You can install vFabric SQLFire from the VMware yum repository (RHEL only), from a downloaded RPM file (RHEL only), or from a downloaded ZIP file. The installation procedure varies according to whether you obtained vFabric SQLFire as a standalone product or as part of VMware® vFabric Suite™ Advanced. Installation Note for vFabric Suite Customers vFabric SQLFire is available as a standalone product installation, and as part of vFabric Suite Advanced. vFabric Suite is a set of runtime components that let you build, scale, and run modern, agile applications in virtual environments. If you obtain SQLFire standalone, you can install it on physical or virtual machines according to the procedures in this document. If you obtain SQLFire as part of vFabric Advanced, you install it exclusively on VMware virtual machines that run on vSphere. The vFabric Suite install process adds the vFabric License Server to an existing vCenter server. The vFabric License Server accepts a network license, actually a pool of licenses for vFabric components, which makes it easy to manage the licensing of all components installed on the VMs. If you obtain SQLFire as part of vFabric Suite Advanced, first complete the license activation and installation procedures in Getting Started with vFabric Suite . Then follow procedures in this document to set up your environment for SQLFire and complete any remaining SQLFire-specific installation and configuration tasks. RHEL Only: Install vFabric SQLFire from an RPM If your operating system is Red Hat Enterprise Linux (RHEL), you can install vFabric SQLFire from an RPM. The RPM installation process can be used whether you have purchased the standalone vFabric SQLFire product or vFabric Suite Advanced, which includes vFabric SQLFire. Use the installation procedure that matches the product(s) that you purchased: • Install SQLFire as a Component of vFabric Suite Advanced on page 22 • Install SQLFire as a Standalone Product on page 24 See Getting Started with vFabric Suite Suite for more information. Prerequisites • Confirm that your system meets the hardware and software requirements described in Supported Configurations and System Requirements on page 3. • If you have not already done so, download and install a compatible JDK or JRE on the RHEL computer or VM. 21 Getting Started with vFabric SQLFire Install SQLFire as a Component of vFabric Suite Advanced If you purchased vFabric Suite Advanced, VMware recommends that you install vFabric SQLFire by first installing the VMware RPM repository and then using yum to perform the actual installation. Follow this procedure: 1. On the RHEL computer, start a terminal either as the root user or as an unprivileged user who has sudo privileges. Note: If you are not logged in as the root user, you must use the sudo command to run the commands in the following steps. 2. Install the vFabric repository RPM using the following wget command, passing it the appropriate URL. The URL differs depending on the version of RHEL you are using. Note: You must run the entire wget command on a single line. Be sure you include | sh at the end, or the RPM installation will not work. For RHEL 5: wget -q -O http://repo.vmware.com/pub/rhel5/vfabric/5.3/vfabric-5.3-suite-installer | sh For RHEL 6: wget -q -O http://repo.vmware.com/pub/rhel6/vfabric/5.3/vfabric-5.3-suite-installer | sh The command performs the following tasks: • Imports the vFabric GNU Privacy Guard (GPG) key. • Installs the vFabric 5.3 repository RPM. • Launches the VMware End User License Agreement (EULA) acceptance and repository configuration script. • Outputs the EULA for you to read; you must answer yes to accept the terms and continue. 3. Use the yum search vfabric or yum search vmware command to view the list of vFabric components that you can install from the VMware repository. For example (output truncated for clarity): yum search vfabric ... ============================= N/S Matched: vfabric ============================= vfabric-5.3-qa-repo.noarch : vFabric 5.3 internal qa repository configuration vfabric-agent.x86_64 : VMware vFabric Agent vfabric-gemfire.noarch : VMware vFabric GemFire vfabric-hyperic-agent.noarch : VMware vFabric Hyperic Agent vfabric-hyperic-server.x86_64 : VMware vFabric Hyperic Server vfabric-insight-dashboard.noarch : com.springsource.insight.dist.vfabric:dashboard-rpm vfabric-license-server.noarch : VMware vFabric License Server vfabric-sqlfire.noarch : VMware vFabric SQLFire ... The vFabric SQLFire RPM is called vfabric-sqlfire. 4. Execute the yum command to install vFabric SQLFire: yum install vfabric-sqlfire 22 vFabric SQLFire User's Guide Installing vFabric SQLFire Note: The yum install command installs the most recent version of the vFabric SQLFire RPM that it finds in all installed repository. If you want to install a different version, you must explicitly specify that version with the yum install command. Use yum search vfabric-sqlfire --showduplicates to find all versions that are available in the installed repositories. The yum command begins the install process, resolves dependencies, and displays the packages it plans to install and the required space. 5. Enter y at the prompt to begin the actual installation. The installer downloads and installs the package, andn displays Complete! when the installation process is finished. 6. (Optional.) Specify that the vfabric-sqlfire process should automatically start when the operating system starts by running the following command: chkconfig --level 35 vfabric-sqlfire on 7. (Optional.) Specify the configuration of the vfabric-sqlfire process by editing the file /etc/sysconfig/sqlfire, which is the file sourced by the script that you will later use to start the SQLFire process (/etc/init.d/vfabric-sqlfire.) The /etc/sysconfig/sqlfire file includes many comments to help you decide whether you need to modify it. Here are additional pointers: • If you do not modify the /etc/sysconfig/sqlfire file but simply use the one installed by default, the vfabric-sqlfire process starts up a server instance in a multicast configuration. • If you want the vfabric-sqlfire process to start up using a locator-based configuration, change the LOCATOR property in the /etc/sysconfig/sqlfire file to local, as shown: LOCATOR=local This configuration allows a local locator process to start along with a local server instance. To add additional remote locators, add their IP address and port to the LOCATOR_IP_STRING as shown in the configuration file as a commented-out example. • If you want to start up only a local locator process and not a local server instance, set the LOCATOR property to locator_only. This sets up a redundant locator configuration; be sure you add the locator IP addresses and port numbers to the LOCATOR_IP_STRING; an example is shown in the configuration file. • Finally, set the LOCATOR property to remote if you want to start a local server instance that relies on having locator processes running on one or more remote hosts. Specify these remote hosts using the LOCATOR_IP_STRING property. 8. Start the processes associated with SQLFire by running the following command: /etc/init.d/vfabric-sqlfire start By default, the process uses an evaluation license; if you have purchased a production license, see Activating vFabric SQLFire Licensing on page 27 for information about configuring it in the /var/opt/vmware/sqlfire/sqlfire.properties file. The RPM installation process creates a skeleton sqlfire.properties file to get you started. To stop, restart, and get status about the processes, pass the stop, restart, and status parameters, respectively, to the /etc/init.d/vfabric-sqlfire script: /etc/init.d/vfabric-sqlfire status 23 Getting Started with vFabric SQLFire Install SQLFire as a Standalone Product If you purchased the standalone product (rather than as part of vFabric Suite Advanced), follow this procedure to download and install only the SQLFire RPM: 1. From the VMware downloads page, select VMware vFabric SQLFire. On the SQLFire 1.1 download page, perform the following steps: • If you are installing SQLFire for evaluation, click on the "Download Free Trial" link, register an account with VMware (if you have not done so already) and download SQLFire. • If you have already purchased SQLFire, locate the vFabric SQLFire licensed offering that you have purchased from the Product Downloads tab. Click on the View Download button. • Download the vFabric SQLFire RPM appropriate for your RHEL operating system. • RHEL 5: vfabric-sqlfire-1.1-1.el5.noarch.rpm • RHEL 6: vfabric-sqlfire-1.1-1.el6.noarch.rpm 2. On the RHEL computer, start a terminal either as the root user or as an unprivileged user who has sudo privileges. Note: If you are not logged in as the root user, you must use the sudo command to run the commands in the following steps. 3. Run the appropriate command to install the vFabric repository RPMs: RHEL 5: sudo rpm -ivh vfabric-sqlfire-1.1-1.el5.noarch.rpm RHEL 6: sudo rpm -ivh vfabric-sqlfire-1.1-1.el6.noarch.rpm The rpm command begins the install process, resolves dependencies, and displays the packages it plans to install. The SQLFire software is installed into the /opt/vmware/vfabric-sqlfire directory. If necessary, the install process creates a sqlfire non-interactive user in the vfabric group. This user owns the installed SQLFire directories and files, including any disk store files that you create later. Note: You cannot log in directly as the sqlfire user because interactive login has been disabled. Rather, you must first log in as the root user or as a user with sudo privileges. You can then execute commands as the sqlfire user by using sudo -u sqlfire command_name . 4. If the installation is successful, you see a [100%] installation status message. For example: Preparing... [100%] 1:vfabric-sqlfire [100%] ########################################### ########################################### 5. If you have not already done so, download and install a compatible JDK or JRE on the RHEL computer or VM. 6. (Optional.) Specify that the vfabric-sqlfire process should automatically start when the operating system starts by running the following command: chkconfig --level 35 vfabric-sqlfire on 24 vFabric SQLFire User's Guide Installing vFabric SQLFire 7. (Optional) Specify the configuration of the vfabric-sqlfire process by editing the file /etc/sysconfig/sqlfire, which is the file sourced by the script that you will later use to start the SQLFire process (/etc/init.d/vfabric-sqlfire.) The /etc/sysconfig/sqlfire file includes many comments to help you decide whether you need to modify it. Here are additional pointers: • If you do not modify the /etc/sysconfig/sqlfire file but simply use the one installed by default, the vfabric-sqlfire process starts up a server instance in a multicast configuration. • If you want the vfabric-sqlfire process to start up using a locator-based configuration, change the LOCATOR property in the /etc/sysconfig/sqlfire file to local, as shown: LOCATOR=local This configuration allows a local locator process to start along with a local server instance. To add additional remote locators, add their IP address and port to the LOCATOR_IP_STRING as shown in the configuration file as a commented-out example. • If you want to start up only a local locator process and not a local server instance, set the LOCATOR property to locator_only. This sets up a redundant locator configuration; be sure you add the locator IP addresses and port numbers to the LOCATOR_IP_STRING; an example is shown in the configuration file. • Finally, set the LOCATOR property to remote if you want to start a local server instance that relies on having locator processes running on one or more remote hosts. Specify these remote hosts using the LOCATOR_IP_STRING property. 8. Start the processes associated with SQLFire by running the following command: /etc/init.d/vfabric-sqlfire start By default, the process uses an evaluation license; if you have purchased a production license, see Activating vFabric SQLFire Licensing on page 27 for information about configuring it in the /var/opt/vmware/sqlfire/sqlfire.properties file. The RPM installation process creates a skeleton sqlfire.properties file to get you started. 9. To stop, restart, and get status about the processes, pass the stop, restart, and status parameters, respectively, to the /etc/init.d/vfabric-sqlfire script: /etc/init.d/vfabric-sqlfire status Install vFabric SQLFire from a ZIP File This procedure describes how to install the SQLFire software on a single computer or VM, for either a peer client or client/server deployments. Repeat the procedure to install and license SQLFire on each physical or virtual machine where you want to run a SQLFire member. Prerequisites 1. Confirm that your system meets the hardware and software requirements described in Supported Configurations and System Requirements on page 3. 2. From the VMware downloads page, select VMware vFabric SQLFire. From the Download VMware vFabric SQLFire 1.1 page, perform the following steps: • If you are installing SQLFire for evaluation, click on the "Download Free Trial" link, register an account with VMware (if you have not done so already) and download SQLFire. • If you have already purchased SQLFire, locate the vFabric SQLFire licensed offering that you have purchased from the Product Downloads tab. Click on the View Download button. Note: You can also get SQLFire from your salesperson. 25 Getting Started with vFabric SQLFire • Download the ZIP file distribution of vFabric SQLFire. Procedure 1. Change to the directory where you downloaded the SQLFire software, and unzip the ZIP file: • UNIX and Linux (Bourne and Korn shells - sh, ksh, bash). If you are using the command line, type the following command: $ unzip vFabric_SQLFire_XX_bNNNNN.zip -d path_to_product where XX corresponds to the product version of SQLFire that you are installing, bNNNNN corresponds to the build number of the software, and path_to_product corresponds to the location where you want to install SQLFire. For example: $ unzip vFabric_SQLFire_11_b40332.zip -d /opt/vmware/vfabric-sqlfire Alternatively, unzip the .zip file directly with any common ZIP extraction tool suitable for your operating system. • Windows: Open the .zip file, and extract the product files to the desired installation location on your machine. 2. Configure your SQLFire license, if you have purchased a production license. Activating vFabric SQLFire Licensing on page 27 provides more information. 3. To begin using the sqlf utility to start servers or execute other commands, add the SQLFire bin directory to your path. For example: export PATH=$PATH:/opt/vmware/vfabric-sqlfire/bin The sqlf script automatically sets the class path relative to the installation directory. 4. Repeat this procedure to install and license SQLFire on each different computer where you want to run a SQLFire member. Obtaining Modified Open Source Code Libraries Many open source licenses require that vendors who use or modify their libraries make that code available. To obtain the open source code libraries modified in SQLFire, visit the product download page, and select the Open Source tab. Download the vFabric_SQLFire_XX_bNNNNN_OSS.zip file (where XX corresponds to the product version of SQLFire that you are installing and bNNNNN corresponds to the build number of the software.) Download and read the associated disclosure information (.txt) file from the same download page. The .zip file contains both the original open source libraries and the modified source libraries. 26 vFabric SQLFire User's Guide Chapter 4 Activating vFabric SQLFire Licensing vFabric SQLFire includes a default evaluation license that enables you to run the product tutorial and perform simple evaluation activities. You can obtain custom evaluation licensing and purchase production licensing from your VMware account manager or the VMware license portal. Understand vFabric SQLFire License Options vFabric SQLFire has a number of licensing options. Read the following sections to understand the different license types. Default Evaluation License The default evaluation license included with SQLFire allows you to run up to three non-production data stores in the distributed system. SQLFire uses the default evaluation license upon startup if custom evaluation or production licensing has not been installed. This license never expires. It is not allowed for production use. Custom Evaluation and Production Licenses To get expanded configuration options and to move into production with SQLFire, contact your VMware account manager. You can obtain custom evaluation licenses for your specific evaluation requirements. You can purchase a production license when you are finished with your evaluation. Your VMware account manager will help you determine the best topology and expiration options for your needs. For information on purchasing SQLFire licensing, see http://www.vmware.com/products/datacenter-virtualization/vfabric-sqlfire/buy.html. Custom evaluation licenses have an expiration date. Production licenses never expire. vFabric SQLFire Professional and Enterprise Licenses vFabric SQLFire uses these main license types for custom evaluation and production licensing: • vFabric SQLFire Professional license. Enables you to deploy a SQLFire distributed system in a production environment. A license is required for each SQLFire distributed system member that hosts data, whether or not they also act as a server in client/server deployments. • vFabric SQLFire Enterprise license. Standalone license that enables you to deploy a SQLFire distributed system in a production environment. This license also enables you to loosely couple SQLFire distributed systems that are at different geographical locations (WAN replication). A license is required for each SQLFire distributed system member that hosts data, whether or not they also act as a server in client/server deployments. Because the vFabric SQLFire Enterprise license is available only as a standalone license and not as part of vFabric Suite, you must install the license in the sqlfire.properties file or as a boot property. You cannot install a vFabric SQLFire Enterprise license in the vFabric License Server. If you install SQLFire using the RPM, this file is located at /var/opt/vmware/sqlfire/sqlfire.properties. 27 Getting Started with vFabric SQLFire SQLFire licenses do not restrict the number of clients that can connect to a distributed system. Any number of thin clients and peer clients (SQLFire accessor members) are permitted. vFabric SQLFire Local Licensing and vFabric Suite Licensing If you obtained vFabric SQLFire as a standalone product, you install a license locally on each physical and virtual machine that runs vFabric SQLFire. If you obtained vFabric SQLFire as part of vFabric Suite, you can either use the vFabric License Server to install your SQLFire licenses, or install the license locally in vSphere virtual machines. To use the vFabric License Server for licensing, you must first install and configure the vFabric License Server. Then you install your SQLFire serial numbers in the vFabric License Server. SQLFire will retrieve your licenses dynamically. To set up the vFabric License Server, see Install vFabric License Server on Your vCenter Server in the vFabric Suite documentation. Note: You cannot use the vFabric License Server to manage licenses on physical machines, or with standalone SQLFire licenses such as vFabric SQLFire Enterprise. Choose a License Option Based on Topology How you plan to use vFabric SQLFire determines which SQLFire license offerings are right for your system. Licensing options are available for the following topologies: • Single-Site System with Multiple Data Stores on page 28 • Multi-Site (WAN) System on page 29 For further information about SQLFire purchase options, refer to http://www.vmware.com/products/datacenter-virtualization/vfabric-sqlfire/buy.html. Single-Site System with Multiple Data Stores Any client/server system or peer-to-peer system requires a vFabric SQLFire license for the SQLFire data stores (SQLFire members that host data). You configure these licenses for each SQLFire member. The vFabric SQLFire Professional license enables you to run multiple data stores in a single cluster, with unlimited clients. Figure 1: Example vFabric SQLFire Professional Deployment If you need to replicate table data across multiple SQLFire clusters, you must purchase and install a standalone vFabric SQLFire Enterprise license. See Multi-Site (WAN) System on page 29. 28 vFabric SQLFire User's Guide Activating vFabric SQLFire Licensing Installing a vFabric SQLFire Professional License 1. Obtain a product vFabric SQLFire Professional license from VMware. 2. Install the license in SQLFire. Choose one of the following options: • On each SQLFire data store member, add the vFabric SQLFire license serial number directly to the sqlfire.properties file. See Option 1: Install Licenses Using sqlfire.properties on page 31; or • Create a file that contains the vFabric SQLFire license serial number, and copy the file to the vFabric serial number directory on each SQLFire data store member. See Option 2: Install Licenses Using Serial Number Files on page 32; or • If you have purchased SQLFire as part of vFabric Suite, install the vFabric SQLFire license using vFabric License Server. See vFabric Suite Only: Configure vFabric SQLFire for vFabric License Server on page 32. Multi-Site (WAN) System If you need to replicate table data across multiple SQLFire clusters (for example, over a WAN), you must purchase and install a standalone vFabric SQLFire Enterprise license. Any number of thin clients and peer clients (SQLFire accessor members) are permitted in each cluster. All systems that participate in the WAN installation must be licensed. The license is configured in each data store member in the distributed system. Any number of thin clients and peer clients (SQLFire accessor members) are permitted in each cluster. Installing a vFabric SQLFire Enterprise License 1. Obtain a vFabric SQLFire Enterprise license. You can use the same serial number in each distributed system; however, as a best practice you should obtain a unique serial number for each distributed system that communicates over the WAN. 29 Getting Started with vFabric SQLFire 2. Install the license in SQLFire. Choose one of the following options: • On each data store member in the distributed system, add the vFabric SQLFire Enterprise serial number directly to the sqlfire.properties file. See Option 1: Install Licenses Using sqlfire.properties on page 31; or • Create a file that contains both the vFabric SQLFire Enterprise serial number, and copy the file to the vFabric serial number directory on all SQLFire data store members. See Option 2: Install Licenses Using Serial Number Files on page 32. 3. If you have obtained unique serial numbers for your other distributed systems, install the unique serial numbers on the other distributed systems by using one of the options described in step 2. How vFabric SQLFire Manages Licensing Before you install vFabric SQLFire licenses, understand how SQLFire manages your licensing information. • How vFabric SQLFire Finds and Verifies Your License on page 30 • License Working Directory on page 30 • Local VMware vFabric Directories on page 31 How vFabric SQLFire Finds and Verifies Your License SQLFire has a default license that it uses if it cannot locate any other valid licensing. Non-default licensing is verified using a combination of the product sqlfire.jar file and the serial numbers you provide, or a license may be acquired dynamically from the vFabric License Server. SQLFire uses the first valid licensing it finds in this list: 1. Serial number specified by the license-serial-number boot property. 2. Dynamic licensing provided from a serial number file stored in the local VMware vFabric serial number directory, configured by specifying license-serial-number=dynamic as a boot property. 3. Dynamic licensing provided by the vFabric License Server, configured by specifying license-serial-number=dynamic as a boot property. If SQLFire cannot validate any of the specified licensing in the above list, the member process does not start and throws an exception. If no licensing is specified, SQLFire uses the default evaluation licensing shipped with the product. License Working Directory SQLFire stores licensing information in a directory on your system. It writes to the first writable directory it finds in this list: 1. The value of the license-working-dir boot property, if specified for the member. 2. The SQLFire member's current working directory as determined by System.getProperty("user.dir") at startup. These are the files that SQLFire writes: 1. License state files with names ending with -license.cfg. Example: vf.sf-license.cfg. 2. License events files with names ending with -events.txt. Example: vf.sf-events.txt. Note: Leave these files alone. Do not edit or delete these files, and do not alter the permissions on the files or the directory where these files are located. These files are created using the default permissions of the user who is starting up the SQLFire process. To stop or start the SQLFire process, a user needs write permissions for this directory and the files in it. Make sure that the permissions for each user are sufficient; otherwise SQLFire may throw an exception during stop or start. 30 vFabric SQLFire User's Guide Activating vFabric SQLFire Licensing Local VMware vFabric Directories The location of the local VMware vFabric home directory, if it exists, varies by operating system: Windows %ALLUSERSPROFILE%\VMware\vFabric Linux (or other OS) /opt/vmware/vFabric The location of the local VMware vFabric serial number directory, if it exists, varies by operating system: Windows %ALLUSERSPROFILE%\VMware\vFabric Linux (or other OS) /etc/opt/vmware/vfabric Install and Configure vFabric SQLFire Licenses Installation is required for all licensing except the default evaluation license, which is used automatically when other licensing is not provided. You do not need to install or configure the default evaluation license. When you obtain custom evaluation licenses or purchase production licenses, you receive one or more serial numbers to use in your SQLFire member configurations. The number of serial numbers that you receive depends on the type of licensing that you purchase. You install licensing in all members that you run as data stores. You do not need to install licensing in your clients (thin client applications or SQLFire accessors). Choose a License Option Based on Topology on page 28 describes the appropriate licensing for each topology. Note: If you obtain SQLFire as part of vFabric Suite, refer first to the license activation procedure in Getting Started with vFabric Suite in the vFabric Suite documentation. Then complete the tasks in this procedure, as necessary, to configure SQLFire-specific licensing. Where to Install Your License If you obtained vFabric SQLFire as a standalone product, you install licenses locally to each SQLFire member by modifying the sqlfire.properties file, or by supplying a boot property when you start the SQLFire member. See Option 1: Install Licenses Using sqlfire.properties on page 31 and Option 2: Install Licenses Using Serial Number Files on page 32. If you are installing SQLFire in a vSphere virtual machine as part of vFabric Suite, you can use the vFabric License Server to install your SQLFire licenses and then configure vFabric SQLFire to communicate with the license server. See vFabric Suite Only: Configure vFabric SQLFire for vFabric License Server on page 32. Note: You cannot use the vFabric License Server if you purchased a standalone SQLFire license, such as vFabric SQLFire Enterprise. Install standalone licenses in sqlfire.properties or as a boot property. Option 1: Install Licenses Using sqlfire.properties Add a license key to the sqlfire.properties file on each data store member in your deployment, or specify the keys as a boot property when you start a SQLFire member using sqlf or the FabricServer interface. Note: If you install vFabric SQLFire using an RPM, the properties file is located at /var/opt/vmware/sqlfire/sqlfire.properties. This is the recommended way to install licensing for standalone SQLFire deployments. (For SQLFire deployments installed on vSphere virtual machines as part of a vFabric Suite deployment, VMware recommends that you use 31 Getting Started with vFabric SQLFire the vFabric License Server. See vFabric Suite Only: Configure vFabric SQLFire for vFabric License Server on page 32.) For example: # sqlfire.properties for data store or accessor member license-serial-number=#####-#####-#####-#####-##### If you need to specify multiple serial numbers, use a comma separated list: # sqlfire.properties for data store or accessor member license-serial-number=#####-#####-#####-#####-#####,#####-#####-#####-#####-##### Option 2: Install Licenses Using Serial Number Files Place serial numbers in serial number files in the VMware vFabric serial number directory. To configure SQLFire to use these for licensing, you specify license-serial-number=dynamic as a boot property. You can specify this property in sqlfire.properties, or when starting a SQLFire member using sqlf or the FabricServer interface. Use this procedure to install and configure serial number files for any standalone SQLFire license. 1. Create a file named vf.sf-serial-numbers.txt and paste the serial number into it. Note: If you have multiple serial numbers, enter each serial number on a new line. 2. Save the file to the appropriate serial numbers directory on each SQLFire member. See Local VMware vFabric Directories on page 31 for the appropriate directory based on your operating system. 3. On all SQLFire data store members, specify license-serial-number=dynamic in sqlfire.properties, or as a boot property. For example: # sqlfire.properties for dynamic licensing of data stores license-serial-number=dynamic vFabric Suite Only: Configure vFabric SQLFire for vFabric License Server You can only use this configuration method if you are running SQLFire on a vSphere virtual machine as part of vFabric Suite. This method is not applicable to installing a standalone vFabric SQLFire license, such as a vFabric SQLFire Enterprise license. To set up vFabric License Server licensing, refer first to the license activation procedure in Activate vFabric Suite Licenses in the vFabric Suite documentation. After you install SQLFire licenses on the vFabric License Server, configure dynamic licensing in SQLFire: 1. Specify license-serial-number=dynamic in the sqlfire.properties file on each data store or accessor member. For example: # sqlfire.properties for dynamic licensing license-serial-number=dynamic Note: If you install vFabric SQLFire using an RPM, the properties file is located at /var/opt/vmware/sqlfire/sqlfire.properties. 2. (Optional) Change the default timeout value (10000) to indicate the maximum time in milliseconds that the member should wait when obtaining a license dynamically from the vFabric License Server. For example, in sqlfire.properties: #timeout in milliseconds license-server-timeout=20000 32 vFabric SQLFire User's Guide Activating vFabric SQLFire Licensing Verify Your License and Check Your License Usage You can verify the validity of your license and monitor your license usage. If you install an invalid serial number or if SQLFire cannot obtain a dynamic license from the vFabric License Server, SQLFire fails to start and throws an exception. In Getting Started with vFabric Suite , see "Check the Validity of an Existing License Key." to learn how to verify your license. See Licensing Problems on page 775 for a list of common problems and their solutions. If you obtained vFabric SQLFire as part of vFabric Suite and want to check your license usage, see Monitoring vFabric License Usage in the vFabric Suite documentation. 33 Chapter 5 Upgrading vFabric SQLFire SQLFire 1.1 is not compatible with persistence files (disk stores) that were created in earlier versions of SQLFire (1.0.x). You must use the sqlf upgrade-disk-store command to upgrade disk stores to the SQLFire 1.1 format after upgrading the SQLFire software to version 1.1. Refer to the Release Notes to learn about changes that were introduced in the latest update. Note: If you installed SQLFire using an RPM from the VMware YUM repository, see RHEL Only: Upgrade vFabric SQLFire from the VMWare YUM RepositoryWhen VMware releases a new maintenance version of SQLFire, the appropriate VMware YUM repository is updated to include the new RPM. You can use yum to quickly upgrade SQLFire to the latest version. for upgrade instructions. Before You Upgrade This section provides information you need to know before you begin to upgrade vFabric SQLFire. • If you obtained SQLFire as part of a vFabric Suite package, first complete the vFabric License Server installation and license activation procedures in Getting Started with vFabric Suite.Then follow procedures in this document to set up your environment for SQLFire and to complete any remaining SQLFire-specific installation and configuration tasks. • During an upgrade from one major SQLFire version to another, you cannot connect members in the same distributed system to other members running a different major version. Therefore, you cannot perform a rolling upgrade between major versions of vFabric SQLFire and will need to plan your system downtime accordingly. See Version Compatibility Rules on page 39 for more information on SQLFire version interoperability. • If your SQLFire deployment uses DBSynchronizer, failover-related issues (such as duplicate rows in the RDBMS) can occur during an upgrade if clients are actively performing DML on synchronized tables. See How Failover and Upgrades Affect Synchronization on page 209 in the DBSynchronizer documentation. • Read the SQLFire Release Notes to familiarize yourself with all feature changes. • Know how to configure environment variables for your system. • Confirm that your system meets the requirements to run SQLFire. See Supported Configurations and System Requirements on page 3. Note: To check your current Java version, type java -version at a command-line prompt. You can download Sun/Oracle Java SE from the following location: http://www.oracle.com/technetwork/java/javase/downloads/index.html. • If you are upgrading from SQLFire 1.0.x you will need to run the sqlf command upgrade-disk-store to upgrade each disk store to a format that is compatible with vFabric SQLFire 1.1 See the upgrade instructions for ZIP files or RPMs for more information. 35 Getting Started with vFabric SQLFire RHEL: Upgrade vFabric SQLFire from RPM If your guest operating system is Red Hat Enterprise Linux (RHEL) and you have installed a previous version of SQLFire using yum and RPM, VMware recommends that you use the RPM distribution to upgrade vFabric SQLFire. You complete the upgrade procedure on every virtual and physical machine that runs SQLFire. Note: Thoroughly test your development systems with the new version before moving into production. When you upgrade vFabric SQLFire on RHEL from RPM, the new software is installed by default into /opt/vmware/vfabric-sqlfire/vFabric_SQLFire_XX where XX corresponds to the version of SQLFire (for example, vFabric_SQLFire_11) that you have installed. No files are overwritten during the upgrade process. Prerequisites • Confirm that your system meets the hardware and software requirements described in Supported Configurations and System Requirements on page 3. • Download the vFabric SQLFire RPM: • From the VMware downloads page, select VMware vFabric SQLFire. • If you are installing SQLFire for evaluation, click the Try Now button to download an evaluation RPM. • If you have purchased SQLFire, download the vFabric SQLFire offering you have purchased from the Product Downloads tab. You can also get SQLFire from your salesperson. • Download the vFabric SQLFire RPM appropriate for your RHEL operating system. • RHEL 5: vfabric-sqlfire-1.1-1.el5.noarch.rpm • RHEL 6: vfabric-sqlfire-1.1-1.el6.noarch.rpm Procedure Upgrade vFabric SQLFire using the RPM: 1. Review the items listed in Prerequisites on page 36 and make any appropriate preparations. 2. Stop all members of the system running with the prior version. For example, use the shut-down-all command: sqlf shut-down-all -locators=localhost[10101] In the sample command, substitute the address and port of a locator for your SQLFire distributed system. To shut down only the local SQLFire process, use the command: /etc/init.d/vfabric-sqlfire stop 3. Execute the following rpm command to install the new SQLFire RPM. If necessary, use sudo to run the command if you are not logged in as root: RHEL 5: sudo rpm -Uvh vfabric-sqlfire-1.1-1.el5.noarch.rpm RHEL 6: sudo rpm -Uvh vfabric-sqlfire-1.1-1.el6.noarch.rpm The rpm command begins the install process, resolves dependencies, and displays the packages it plans to install. 36 vFabric SQLFire User's Guide Upgrading vFabric SQLFire 4. If you are upgrading from SQLFire 1.0.x, run the sqlf command upgrade-disk-store to upgrade each disk store to a format that is compatible with vFabric SQLFire 1.1. See sqlf upgrade-disk-store on page 422 for more information. Note: You must update the default disk stores as well as any additional disk stores that were defined through the CREATE DISKSTORE statement. Specify the full path to each disk store in multiple invocations of the sqlf upgrade-disk-store command. SQLFire creates default disk stores in each SQLFire server or locator directory, as well as in the /datadictionary subdirectory of each SQLFire server or locator directory. The example below shows how to upgrade these default disk stores on a single member; you must repeat the commands on each machine that hosts a locator or server. By default, SQLFire disk store files are owned by the user sqlfire, and you must preserve the ownership of these files when upgrading the disk store. Use the sudo command to perform the upgrade commands as the sqlfire user, as in these example commands: sudo -u sqlfire sqlf upgrade-disk-store SQLF-DEFAULT-DISKSTORE /var/opt/vmware/sqlfire/server sudo -u sqlfire sqlf upgrade-disk-store SQLF-DD-DISKSTORE /var/opt/vmware/sqlfire/server/datadictionary Replace /var/opt/vmware/sqlfire/server with the actual server or locator directory. 5. 6. 7. 8. Repeat the previous step to upgrade each default and user-defined disk store on the local system. Repeat all previous steps for every virtual or physical machine on which you run a vFabric SQLFire member. Restart all system members according to your usual procedures. Beginning with version 1.1.1, SQLFire stores normalized (all-uppercase) user names. The normalized user names are also used for password encryption. If you configured users in the previous release and the user names were not in all-uppercase letters, also complete these steps: a. Use the sqlf encrypt-password command to regenerate encrypted passwords for any system users that were defined in the previous software release using mixed-case characters. b. Use SYS.CHANGE_PASSWORD to regenerate passwords for all other users that were created using mixed-case characters. What to Do Next After you have upgraded, perform the following tasks: • Run the product tutorial and examples. See Tutorials on page 43. • Test your development systems with the new version. Upgrade vFabric SQLFire from a ZIP File Upgrade vFabric SQLFire on every virtual and physical machine that will run SQLFire, using the downloaded SQLFire ZIP file. Procedure Note: Thoroughly test your development systems with the new version before moving into production. 1. Review the items listed in Before You Upgrade on page 35 and make any appropriate preparations. 37 Getting Started with vFabric SQLFire 2. Stop all members of the system running the prior version of SQLFire. For example, in a SQLFire deployment you can use the shut-down-all command to stop all members of the distributed system: sqlf shut-down-all -locators=mylocator[10101] 3. Install the latest version of SQLFire in a different directory than the existing version. See Install vFabric SQLFire from a ZIP File on page 25. Note: SQLFire is installed as a complete product, rather than as a modification to a prior version. The Java JRE runtime environment is not bundled with SQLFire, so you need to install and configure an appropriate JDK or JRE to comply with SQLFire requirements and your unique system needs. 4. If you are upgrading from SQLFire 1.0.x, run the sqlf command upgrade-disk-store to upgrade each disk store to a format that is compatible with vFabric SQLFire 1.1. See sqlf upgrade-disk-store on page 422 for more information. Note: Update the default disk stores as well as any additional disk stores that were defined through the CREATE DISKSTORE statement. Specify the full path to each disk store in multiple invocations of the sqlf upgrade-disk-store command. SQLFire creates default disk stores in each SQLFire server or locator directory, as well as in the /datadictionary subdirectory of each SQLFire server or locator directory. The example below shows how to upgrade these default disk stores on a single member; you must repeat the commands on each machine that hosts a locator or server. By default, SQLFire disk store files are owned by the user sqlfire, and you must preserve the ownership of these files when upgrading the disk store. Use the sudo command to perform the upgrade commands as the sqlfire user, as in these example commands: sudo -u sqlfire sqlf upgrade-disk-store SQLF-DEFAULT-DISKSTORE /var/opt/vmware/sqlfire/server sudo -u sqlfire sqlf upgrade-disk-store SQLF-DD-DISKSTORE /var/opt/vmware/sqlfire/server/datadictionary Replace /var/opt/vmware/sqlfire/server with the actual server or locator directory. 5. Repeat the previous step to upgrade each default and user-defined disk store on the local system. 6. Redeploy your environment's license or configuration files to the new version's installation. Copy and edit the files as necessary to point to the new installation directory. 7. Restart all system members according to your usual procedures. 8. Beginning with version 1.1.1, SQLFire stores normalized (all-uppercase) user names. The normalized user names are also used for password encryption. If you configured users in the previous release and the user names were not in all-uppercase letters, also complete these steps: a. Use the sqlf encrypt-password command to regenerate encrypted passwords for any system users that were defined in the previous software release using mixed-case characters. b. Use SYS.CHANGE_PASSWORD to regenerate passwords for all other users that were created using mixed-case characters. What to Do Next After you have upgraded, perform the following tasks: • Run the product tutorial and examples. See Tutorials on page 43. • Test your development systems with the new version. 38 vFabric SQLFire User's Guide Upgrading vFabric SQLFire Version Compatibility Rules Upgraded SQLFire members cannot participate in a distributed system that contains SQLFire members from an earlier version. Shut down all existing cluster members before restarting the cluster with upgraded SQLFire members. Thin clients from earlier versions of SQLFire can operate against the latest version of SQLFire. However, thin clients using the latest SQLFire JDBC drivers are not compatible with older versions of SQLFire. Refer to the Release Notes to learn about changes that were introduced in the latest update. Note: Beginning with version 1.1.1, SQLFire stores normalized (all-uppercase) user names. The normalized user names are also used for password encryption. Any hashed passwords that were generated using the sqlf encrypt-password command for system users (defined in sqlfire.properties or otherwise) that are not in all upper-case characters must be regenerated. Similarly, all users that were created using the SYS.CREATE_USER procedure must regenerate passwords using SYS_CHANGE_PASSWORD, if the user name was previously not in all upper-case characters. 39 Chapter 6 Connect to vFabric SQLFire with JDBC Tools Third-party JDBC tools can help you browse data in tables, issue SQL commands, design new tables, and so forth. You can configure these tools to use the SQLFire JDBC thin client driver to connect to a SQLFire distributed system. Although the instructions for setting up each tool vary, the general process for establishing a connection involves configuring the JDBC client driver and setting JDBC connection URL properties. Follow these basic steps: 1. In the third-party tool, choose to configure a new driver, and select the sqlfireclient.jar file that contains the SQLFire JDBC client driver. This file is installed in the lib directory of your SQLFire installation. 2. If the tool does not automatically select a driver class, you will generally have the option of selecting a class from within the JAR file. For SQLFire, select the com.vmware.sqlfire.jdbc.ClientDriver class. 3. In order to use the client driver, you must specify a JDBC connection URL for your SQLFire distributed system. The basic URL format for the client driver is: jdbc:sqlfire://hostname:port/ where hostname and port correspond to the -client-bind-address and -client-port value of a SQLFire server or locator in your distributed system. 4. Your tool may require that you specify a username and password to use for connecting to the system. If the SQLFire server or locator enables authentication (using the -auth-provider boot property), then enter a valid username and password combination to connect to the distributed system. If authentication is disabled, specify "app" as both the username and password values, or any other temporary value. Note: SQLFire uses the username specified in the JDBC connection as the schema name when you do not provide the schema name for a database object. SQLFire uses "APP" as the default schema. If your system does not enable authentication, you can specify "APP" for both the username and password to maintain consistency with the default schema behavior. For a full example of configuring SQLFire with a third-party JDBC tool, see Connecting to VMware vFabric SQLFire using SQuirreL SQL on the SQLFire community site. 41 Chapter 7 Tutorials Learn to configure and use SQLFire features such as table replication and partitioning, persisting data to disk, and dynamically resizing the cluster. Main Steps The tutorial is divided into the following steps, which explain how to set up a cluster of SQLFire servers on multiple Java VMs and then distribute data across the cluster. Perform the steps in the sequence shown. Step Description Step 1 Create a SQLFire Cluster on page 43 Step 2 Connect to the Cluster Using SQLF on page 45 Step 3 Create Replicated Tables and Execute Queries on page 46 Step 4 Implement a Partitioning Strategy on page 47 Step 5 Persist Tables to Disk on page 49 Step 6 Add Servers to the Cluster and Stop Servers on page 51 Prerequisites Install SQLFire on your local computer as described in Install vFabric SQLFire from a ZIP File on page 25. Create a SQLFire Cluster In this procedure you set up and start a cluster of two SQLFire servers. Procedure 1. Begin by opening a command prompt or terminal window on the computer or VM where you installed SQLFire. 2. Move to the directory in which you installed the SQLFire software. This tutorial uses the example directory ~/vFabric_SQLFire_11_b NNNNN, but you should substitute the actual path to your installation. For example: cd ~/vFabric_SQLFire_11_bNNNNN 3. The initial SQLFire cluster in this tutorial contains two standalone SQLFire server members. Create a new directory for each server: mkdir server1 mkdir server2 Each server will use its local directory to write log files, backup disk store files, a datadictionary directory for persisting data, and a single status file, .sqlfserver.ser. 43 Getting Started with vFabric SQLFire 4. To manage client connections to the available SQLFire server members, the cluster in this tutorial uses a SQLFire locator member. Create a new directory for the locator member: mkdir locator A locator maintains a list of available servers in the cluster, and updates that list as servers join and leave the cluster. Locators also load balance client connections across all available servers. 5. To start or stop a SQLFire locator or a SQLFire server, you use the sqlf script (for Linux platforms) or sqlf.bat script (for Windows platforms). In either case, you must first ensure that the path to the SQLFire bin directory is part of your PATH environment variable. For example, on a Linux platform enter: export PATH=$PATH:~/vFabric_SQLFire_11_bNNNNN/bin On a Windows platform enter: set Path=%Path%;c:\vFabric_SQLFire_11_bNNNNN\bin 6. When you start a SQLFire distributed system, always begin by starting the locator member. Use the sqlf locator command to start the locator in the specified directory: sqlf locator start -dir=locator -peer-discovery-address=ip_address -peer-discovery-port=10101 \ -client-bind-address=ip_address -client-port=1527 Note: In this step and in all subsequent steps, replace ip_address with the IP address of your local system. The -peer-discovery-address and -peer-discovery-port combination defines a unique connection that all members of this SQLFire distributed system use for communicating with one another. Note: Always use a unique -peer-discovery-port number to avoid joining a cluster that is already running on your network. If other people might be evaluating SQLFire on your network, choose a port number other than 10101. The -client-bind-address and -client-port combination defines the connection that client applications use to connect to this locator. In this tutorial, all SQLFire members run on the local computer's IP address and use different port numbers to define unique connections. You can verify the peer and client connections in the locator startup messages, which are similar to: Starting SQLFire Locator using peer discovery on: ip_address[10101] Starting network server for SQLFire Locator at address localhost/127.0.0.1[1527] SQLFire Locator pid: 41149 status: running Note: By starting the locator member first, the locator can manage cluster membership from the start as new servers join and leave the distributed system. The locator member should also be the last process that you shut down when you want to stop a SQLFire distributed system. Note: As an alternative, SQLFire members can discover each other using multicast messaging. However, important SQLFire features such as WAN replication and user authentication require that a SQLFire system use locators rather than multicast for discovery. See Configuring Discovery Mechanisms on page 229. 7. Now use the sqlf server command to start both SQLFire server members and join them to the distributed system: sqlf server start -dir=server1 -locators=ip_address[10101] -client-bind-address=ip_address -client-port=1528 44 vFabric SQLFire User's Guide Tutorials sqlf server start -dir=server2 -locators=ip_address[10101] -client-bind-address=ip_address -client-port=1529 In each command, the -locators option defines the peer discovery address to use for joining the SQLFire distributed system. (Production deployments generally use multiple locator members, in which case you would specify a comma-separated list of locator host[port] connections when starting a server.) Again, the combination of -client-bind-address and -client-port indicates that each server will listen for thin clients on a unique connection (ip_address:1528 and ip_address:1529, respectively). However, in this distributed system all clients will connect using the locator instead of making direct connections to servers. 8. Both SQLFire servers output messages similar to: Starting SQLFire Server using locators for peer discovery: ip_address[10101] Starting network server for SQLFire Server at address /ip_address[1528] SQLFire Server pid: 41502 status: running Distributed system now has 2 members. Other members: localhost(41149:locator):32977/50114 Logs generated in /Users/yozie/vFabric_SQLFire_11_bNNNNN/server1/sqlfserver.log Starting SQLFire Server using locators for peer discovery: ip_address[10101] Starting network server for SQLFire Server at address /ip_address[1529] SQLFire Server pid: 41533 status: running Distributed system now has 3 members. Other members: localhost(41149:locator):32977/50114, 10.0.1.11(41502:datastore):49915/50462 Logs generated in /Users/yozie/vFabric_SQLFire_11_bNNNNN/server2/sqlfserver.log Startup messages show the cluster membership details. By default, new SQLFire servers host data as data stores, and are automatically added to a default server group. You can optionally specify server group membership at startup using the server-groups boot property. Connect to the Cluster Using SQLF sqlf implements a command-line tool that is based on the Apache Derby ij tool. You can use sqlf to connect to a SQLFire cluster and run scripts or interactive queries. You execute sqlf using the sqlf or sqlf.bat script. Procedure 1. In the same command prompt or terminal Window in which you started the SQLFire cluster, change to the quickstart directory: cd quickstart The quickstart directory contains example SQL script files that you will use later in the tutorial. 2. Start an interactive sqlf session: sqlf This command starts the interactive shell and displays the prompt: sqlf>. 3. Print a brief list of the available sqlf commands: help; 45 Getting Started with vFabric SQLFire 4. To connect to the SQLFire cluster using the JDBC thin client driver, use the connect client command and specify the host and port number of the SQLFire locator: connect client 'ip_address:1527'; Notice that SQLFire does not have the concept of a "database". When you connect to a SQLFire cluster, the distributed system that you connect to is defined by the locator (or alternately, the mcast-port) specified in the JDBC or ADO.NET connection. 5. Use the following command to view tables in the "sys" schema: show tables in sys; You will use information from many of these tables to view information and statistics about a working SQLFire cluster. 6. The sys.members table stores information about the SQLFire members. Execute the following query to see the unique ID assigned to the two SQLFire servers and the locator that you started: select id from sys.members; You will see output similar to: ID ------------------------------0.0.1.11(41533):52614/50508 localhost(41149):32977/50114 10.0.1.11(41502):49915/50462 3 rows selected The output displays the member process ID that is also logged when you start the members at the command line (41149, 41502, and 41533 in the tutorial example). Create Replicated Tables and Execute Queries By default SQLFire replicates tables to members of the cluster. In this procedure you create new tables that are replicated the SQLFire cluster. Procedure 1. In the same sqlf session, run the ToursDB_schema.sql script to create the tables associated with the ToursDB sample database: run 'ToursDB_schema.sql'; You see DDL output such as: sqlf> CREATE TABLE AIRLINES ( AIRLINE CHAR(2) NOT NULL CONSTRAINT AIRLINES_PK PRIMARY KEY, AIRLINE_FULL VARCHAR(24), BASIC_RATE DOUBLE PRECISION, DISTANCE_DISCOUNT DOUBLE PRECISION, BUSINESS_LEVEL_FACTOR DOUBLE PRECISION, FIRSTCLASS_LEVEL_FACTOR DOUBLE PRECISION, ECONOMY_SEATS INTEGER, BUSINESS_SEATS INTEGER, FIRSTCLASS_SEATS INTEGER ); 46 vFabric SQLFire User's Guide Tutorials 0 rows inserted/updated/deleted [...] 2. Run the loadTables.sql script to populate the tables with data: run 'loadTables.sql'; The script output completes with: sqlf> insert into FLIGHTAVAILABILITY values ('US1357',2,'2004-04-18',0,0,3); 1 row inserted/updated/deleted 3. Enter the following command to show the table names that you created (tables in the APP schema): show tables in APP; 4. The new tables that you create and the data that you load are replicated on the two SQLFire servers by default. You can check whether tables are partitioned or replicated by querying information in sys.systables. Use the following query to check the data policy that SQLFire has assigned to the tables you just created: select tablename, datapolicy from sys.systables where tableschemaname='APP'; The output shows that each of the ToursDB tables that you created are replicated. SQLFire replicates tables by default if you do not use the PARTITION BY clause in the CREATE TABLE statement. Partitioning Tables on page 67 and Replicating Tables on page 77 provide more information about creating tables in SQLFire. 5. You can also use the sys.members table to determine which members host a particular table: select id from sys.systables s, sys.members where s.tablename='FLIGHTS'; In the tutorial, both of the SQLFire servers store information for each replicated table. 6. SQLFire provides query features similar to those available in other data management products. For example, the following command executes a simple query: SELECT city_name, country, language FROM cities WHERE language LIKE '%ese'; The following query executes a join between tables: SELECT city_name, countries.country, region, language FROM cities, countries WHERE cities.country_iso_code = countries.country_iso_code AND language LIKE '%ese'; Implement a Partitioning Strategy In this procedure you drop all tables in the ToursDB schema and then recreate them using a new partitioning and replication strategy. The ToursDB schema in this tutorial is similar to a 'STAR' schema, having only a few fact tables and several dimension tables. Dimension tables are generally small and change infrequently, but are commonly used in join queries. Dimension tables are good candidates for replicating across SQLFire members, because join queries can execute in parallel. The AIRLINES, CITIES, COUNTRIES, and MAPS tables are treated as dimension tables, and are replicated across the SQLFire cluster. In the tutorial it is assumed that applications frequently join these related tables based on the FLIGHT_ID column, which is chosen as the partitioning column. 47 Getting Started with vFabric SQLFire FLIGHTS, FLIGHTS_HISTORY, and FLIGHTAVAILABILITY are fact tables, and they will be partitioned. You will co-locate these tables to ensure that all rows that are associated with FLIGHT_ID are maintained in a single partition. This step ensures that frequent join queries based on a selected flight are pruned to a single member and executed efficiently. Procedure 1. In a separate terminal window or GUI editor, open the create_colocated_schema.sql file in the vFabric_SQLFire_11_bNNNNN/quickstart directory to examine the included DDL commands. The SQL script begins by dropping the existing tables in the schema: DROP DROP DROP DROP DROP DROP DROP TABLE TABLE TABLE TABLE TABLE TABLE TABLE AIRLINES; CITIES; COUNTRIES; FLIGHTAVAILABILITY; FLIGHTS; MAPS; FLIGHTS_HISTORY; Dimension tables can be replicated using the same basic CREATE statement from the preceding section of the tutorial. However, this script explicitly adds the REPLICATE keyword for clarity. For example: CREATE TABLE AIRLINES ( AIRLINE CHAR(2) NOT NULL CONSTRAINT AIRLINES_PK PRIMARY KEY, AIRLINE_FULL VARCHAR(24), BASIC_RATE DOUBLE PRECISION, DISTANCE_DISCOUNT DOUBLE PRECISION, BUSINESS_LEVEL_FACTOR DOUBLE PRECISION, FIRSTCLASS_LEVEL_FACTOR DOUBLE PRECISION, ECONOMY_SEATS INTEGER, BUSINESS_SEATS INTEGER, FIRSTCLASS_SEATS INTEGER ) REPLICATE; The FLIGHTS table is partitioned based on the FLIGHT_ID column: CREATE TABLE FLIGHTS ( FLIGHT_ID CHAR(6) NOT NULL , SEGMENT_NUMBER INTEGER NOT NULL , ORIG_AIRPORT CHAR(3), DEPART_TIME TIME, DEST_AIRPORT CHAR(3), ARRIVE_TIME TIME, MEAL CHAR(1), FLYING_TIME DOUBLE PRECISION, MILES INTEGER, AIRCRAFT VARCHAR(6), CONSTRAINT FLIGHTS_PK PRIMARY KEY ( FLIGHT_ID, SEGMENT_NUMBER), CONSTRAINT MEAL_CONSTRAINT CHECK (meal IN ('B', 'L', 'D', 'S')) ) PARTITION BY COLUMN (FLIGHT_ID); The remaining facts tables are also partitioned, and also colocated with the FLIGHTS table. For example: CREATE TABLE FLIGHTAVAILABILITY ( FLIGHT_ID CHAR(6) NOT NULL , 48 vFabric SQLFire User's Guide Tutorials SEGMENT_NUMBER INTEGER NOT NULL , FLIGHT_DATE DATE NOT NULL , ECONOMY_SEATS_TAKEN INTEGER DEFAULT 0, BUSINESS_SEATS_TAKEN INTEGER DEFAULT 0, FIRSTCLASS_SEATS_TAKEN INTEGER DEFAULT 0, CONSTRAINT FLIGHTAVAIL_PK PRIMARY KEY ( FLIGHT_ID, SEGMENT_NUMBER, FLIGHT_DATE), CONSTRAINT FLIGHTS_FK2 Foreign Key ( FLIGHT_ID, SEGMENT_NUMBER) REFERENCES FLIGHTS ( FLIGHT_ID, SEGMENT_NUMBER) ) PARTITION BY COLUMN (FLIGHT_ID) COLOCATE WITH (FLIGHTS); 2. In the sqlf session, execute the create_colocated_schema.sql script to drop the existing tables and recreate them with the new partitioning and replication strategy. Execute loadTables.sql to populate the tables with data: run 'create_colocated_schema.sql'; run 'loadTables.sql'; 3. Confirm that the tables are created: show tables in APP; 4. Verify whether individual tables are replicated or partitioned: select tablename, datapolicy from sys.systables where tableschemaname='APP'; 5. The FLIGHTS table and others are now partitioned across the SQLFire cluster. Query the sys.members table again to display the member IDs that host the table: select id from sys.systables s, sys.members where s.tablename='FLIGHTS'; 6. Now use the DSID Function to see how many rows of the partitioned FLIGHT table are stored on that SQLFire server. For example: select count(*) memberRowCount, dsid() from flights group by dsid(); 7. Execute a join on both partition members in parallel. select * from flights f, flightavailability fa where f.flight_id = fa.flight_id and f.flight_id = 'AA1116'; The combined results are returned. Because the table is partitioned by FLIGHT_ID, the execution of the join is pruned to the partition that stores the value 'AA1116.' You can verify that flight_id 'AA1116' is located on only one data store using the query: select count(*), dsid() from flights where flight_id = 'AA1116'; Persist Tables to Disk By default, a SQLFire distributed system persists only the data dictionary for the tables and indexes you create. These persistence files are stored in the datadictionary subdirectory of each locator and data store that joins the distributed system. Table data, however, is not persisted by default; if you shut down al SQLFire members, the tables are empty on the next startup. In this procedure you will persist table data to disk. 49 Getting Started with vFabric SQLFire Procedure 1. In a separate terminal window or GUI editor, examine the contents of the create_persistent_schema.sql script. Notice that this script uses the PERSISTENT keyword in each CREATE TABLE statement. For example: CREATE TABLE COUNTRIES ( COUNTRY VARCHAR(26) NOT NULL CONSTRAINT COUNTRIES_UNQ_NM Unique, COUNTRY_ISO_CODE CHAR(2) NOT NULL CONSTRAINT COUNTRIES_PK PRIMARY KEY, REGION VARCHAR(26), CONSTRAINT COUNTRIES_UC CHECK (country_ISO_code = upper(country_ISO_code) ) ) REPLICATE PERSISTENT; 2. In the sqlf session, execute the create_persistent_schema.sql script, then load table data: run 'create_persistent_schema.sql'; run 'loadTables.sql'; 3. Exit the sqlf session: exit; 4. Now list the contents of each SQLFire server directory: ls -l ../server1 ../server2 Notice that each SQLFire directory now contains several disk store files to manage the table data on disk. For example: BACKUPSQLF-DEFAULT-DISKSTORE.if BACKUPSQLF-DEFAULT-DISKSTORE_1.crf BACKUPSQLF-DEFAULT-DISKSTORE_1.drf 5. Because the data is persisted to disk, SQLFire will recover data from disk even if you shut down the data stores. Use the shut-down-all command to shut down all data stores in the cluster, and then restart the servers: cd ~/vFabric_SQLFire_11_bNNNNN sqlf shut-down-all -locators=ip_address[10101] Connecting to distributed system: locators=ip_address[10101] Successfully shut down 2 members sqlf server start -dir=server1 -locators=ip_address[10101] -client-bind-address=ip_address -client-port=1528 -sync=false sqlf server start -dir=server2 -locators=ip_address[10101] -client-bind-address=ip_address -client-port=1529 -sync=false Note: By default, SQLFire servers and locators start to a "waiting" state if the member depends on another server or locator for disk store synchronization. The server automatically continues booting after any dependent servers or locators start. If you start servers from within a shell script, you can use the sqlf locator on page 391 or sqlf server on page 405 command to wait for members to reach the running state before continuing. As an alternative, you can monitor the current status of SQLFire members using STATUS column in the MEMBERS system table. When you restart the servers, you may notice messages similar to: [info 2012/07/24 10:18:11.949 PDT
tid=0x1] Region /_DDL_STMTS_META_REGION initialized with data from 50 vFabric SQLFire User's Guide Tutorials /10.118.33.206:/Users/yozie/vFabric_SQLFire_11_bNNNNN/server1/./datadictionary created at timestamp 1343149012698 version 0 diskStoreId 1fc6a853-69d6-4ffe-8029-218acf165c34 is waiting for the data previously hosted at [/10.118.33.206:/Users/yozie/vFabric_SQLFire_11_bNNNNN /server2/./datadictionary created at timestamp 1343149035681 version 0 diskStoreId 49c1e827-4bb5-49cc-951b-221d47bbc92f] to be available These are not error messages. They indicate that the SQLFire member you are starting is waiting for another member to become available online. 6. Now verify that the persistent tables were reloaded: sqlf connect client 'ip_address:1527'; select id from sys.systables s, sys.members where s.tablename='FLIGHTS'; select count(*) memberRowCount, dsid() from flights group by dsid(); Add Servers to the Cluster and Stop Servers SQLFire manages data in a flexible way that enables you to expand or contract your cluster at runtime to support different loads. To dynamically add more capacity to a cluster, you add new server members and specify the -rebalance option. Procedure 1. Open a new terminal or command prompt window, and create a directory for the new server. Also set your PATH in the new terminal if necessary: cd ~/vFabric_SQLFire_11_bNNNNN mkdir server3 export PATH=$PATH:~/vFabric_SQLFire_11_bNNNNN/bin 2. Start the new server with a unique port number and specify the -rebalance option: sqlf server start -dir=server3 -locators=ip_address[10101] -client-bind-address=ip_address -client-port=1530 -rebalance 3. View the contents of the new SQLFire directory: ls server3 Notice that the new SQLFire server also persists the available table data, and contains the same disk store files as the other two servers. 4. You can view all members of the distributed system using sqlf. In the available sqlf session, execute the query: select id from sys.members; 5. Verify that all servers now host the data: select id from sys.systables s, sys.members where s.tablename='FLIGHTS'; 6. Examine the table data that each server hosts: select count(*) memberRowCount, dsid() from flights group by dsid(); 7. Exit the sqlf session: exit; 51 Getting Started with vFabric SQLFire 8. You can stop an individual SQLFire server by using the sqlf server stop command and specifying the server directory. To shut down all data stores at once, use the sqlf shut-down-all command: sqlf shut-down-all -locators=ip_address[10101] Connecting to distributed system: locators=ip_address[10101] Successfully shut down 3 members 9. After all data stores have stopped, shut down the locator as well: sqlf locator stop -dir=locator1 Perform Additional Tasks After you complete the SQLFire tutorial, you can perform related tutorial tasks to explore other areas of the product. Explore the toursDB Database The example toursDB database manages information about air transportation for scheduling flights. If you need quick access to a database to use when trying SQLFire features, toursDB DDL and data script sare available in the quickstart directory. To view the toursDB schema, see ToursDB sample database Explore SQLFire Language Extensions The tutorial introduces the basics of partitioning, replication, and perisistence using simple modifications to the toursDB DDL. See SQL Statements on page 486 to begin learning about other features that are implemented in SQLFire DDL. You can copy and modify the create_colocated_schema.sql as necessary to implement new features. 52 vFabric SQLFire User's Guide Chapter 8 vFabric SQLFire Features and Benefits The sections that follow summarize main features. The SQLFire community site provides additional information about the features and benefits of SQLFire and a comparison of SQLFire to other data management systems. See also the SQLFire product page. In-Memory Data Management with Optimized Disk Persistence SQLFire enables applications to manage data entirely in memory by using partitioning and synchronous replication to distribute the data across numerous SQLFire members. SQLFire also provides an optimized disk persistence mechanism with a non-flushing algorithm to maintain high performance in applications that require stable, long-term storage. Applications can also use SQLFire to actively cache table data from a traditional disk-based RDBMS. Continuous Availability, Elastically Scaled, Low Latency A flexible architecture enables SQLFire to pool memory and disk resources from hundreds of clustered members. This clustered approach provides extremely high throughput, predictable latency, dynamic and linear scalability, and continuous availability of data. By collocating application logic with data and executing application logic in parallel, SQLFire substantially increases application throughput. It also transparently re-executes application logic if a server fails. Highly Adaptable to Existing Applications SQLFire is implemented entirely in Java, and it can be embedded directly within a Java application. You can also deploy SQLFire members as standalone servers that participate in a cluster. Java applications can connect to a SQLFire cluster using the provided JDBC drivers. Microsoft .NET and Mono applications can connect using the provided ADO.NET driver. The use of JDBC, ADO.NET, and SQL means that many existing database applications can be easily adapted to use a SQLFire cluster. SQLFire introduces several extensions to common SQL Data Definition Language (DDL) statements to manage data partitioning, replication, synchronization with data sources, and other features. However, most common queries and Data Manipulation Language (DML) statements are based on ANSI SQL-92, so experienced database application developers can use their knowledge of SQL when working with SQLFire. 53 Part 4 Managing Your Data in vFabric SQLFire Managing Your Data in vFabric SQLFire describes how to design your database schema to take advantage of replication and partitioning in a distributed SQLFire cluster. You can use this information to design new databases, or to adapt an existing database for use with SQLFire. This guide also describes how to persist your data to disk store files, and it provides a simple procedure for importing an existing database into SQLFire. Topics: • • • • • • • • Designing vFabric SQLFire Databases Using Server Groups to Manage Data Partitioning Tables Replicating Tables Estimating Memory Requirements Using Disk Stores to Persist Data Exporting and Importing Data with vFabric SQLFire Using Table Functions to Import Data as a SQLFire Tables 55 Chapter 9 Designing vFabric SQLFire Databases Unlike in traditional database design, SQLFire requires the designer to analyze the common access patterns and choose a partitioning strategy that results in queries that are pruned to a single partition. In addition, fact tables may need to be replicated in order to make data available for join operations against partitioned data. This chapter describes the basic table design principles that you can use to achieve linear scaling with SQLFire. Design Principles of Scalable, Partition-Aware Databases A key design principle for linear scaling is a partitioning strategy that allows most data access (queries) to be pruned to a single partition, thus avoiding expensive locking or latching across multiple partitions during query execution. In a highly concurrent system having thousands of connections, multiple queries are uniformly spread across the entire data set (and therefore across all partitions), and increasing the number of data stores enables linear scalability. Given sufficient network performance, more connections can be supported without degrading the response time. Note: SQLFire supports distributed queries by parallelizing the query execution across data stores. However, each query instance on a partition can only join rows that are collocated with the partitioned data. This means that queries can join rows between a partitioned table and any number of replicated tables hosted on the data store with no restrictions. But queries that join multiple, partitioned tables have to be filtered based on the partitioning key. Query examples are provided in this section and in Query Capabilities and Limitations on page 768. Identify Entity Groups and Partitioning Keys In relational database terms, an entity group corresponds to rows that are related to one another through foreign key relationships. Members of an entity group are typically related by parent-child relationships and can be managed in a single partition. To design a SQLFire database for data partitioning, begin by identifying "entity groups" and their associated partitioning keys. For example: • In a customer order management system, most transactions operate on data related to a single customer at a time. Queries frequently join a customer's billing information with their orders and shipping information. For this type of application, you partition related tables using the customer identity. Any customer row along with their "order" and "shipping" rows forms a single entity group having the customer ID as the entity group identity (partitioning key). Partitioning related tables using the customer identity enables you to scale the system linearly as you add more members to support additional customers. • In a system that manages a comprehensive product catalog (product categories, product specifications, customer reviews, rebates, related products, and so forth) most data access focuses on a single product at a time. In such a system, you would partition your data on the product key. 57 Managing Your Data in vFabric SQLFire • In an online auction application, you may need to stream incoming auction bids to hundreds of clients with very low latency. To do so, you must manage selected "hot" auctions on a single partition so that they receive sufficient processing power. As the processing demand increases, add more partitions and route the application logic that matches bids to clients to the data store itself. • In a financial trading engine that constantly matches bid prices to asking prices for thousands of securities, partition data using ID of the security. When market data for a security changes, all of the related reference data is co-located with the matching algorithm to ensure low-latency execution. Life beyond Distributed Transactions provides additional background information about entity groups and distributed systems. Creating Partitioned Tables on page 70 describes other ways to partition a table in SQLFire. Use Entity Groups Instead of "Sharding" Sharding is a common strategy in traditional databases where database rows are horizontally partitioned into multiple "database shards." There are a number of differences between application-assisted or system-assisted sharding and SQLFire partition-aware database design: • Rebalancing: SQLFire rebalances the data automatically by making sure that related rows are migrated together and without any integrity loss. This enables you to add capacity as needed. • Distributed transactions: SQLFire transaction boundaries are not limited to a single partition. Atomicity and isolation guarantees are provided across the entire distributed system. • Parallel scatter-gather: Queries that cannot be pruned to a single partition are automatically executed in parallel on data stores. Joins can be performed between tables with the restriction that the joined rows are in fact collocated. • Subqueries on remote partitions: Even when a query is pruned to a single partition, the query can execute subqueries that operate on data that is stored on remote partitions. Replicate Code Tables The "star" schema is the most common relational design pattern. In a star schema, large "fact" tables have foreign key relationships to one or more "code" or "dimension" tables. With SQLFire, you should denormalize code tables into fact tables when possible. When this is not possible, determine whether code tables can be replicated in the SQLFire cluster. The main goal is to partition the entities in fact tables, but to replicate the rows in slow-changing code tables on each member where the partitions are managed. In this way, a join between the fact table and any number of its code tables can be executed concurrently on each partition, without requiring network hops to other members. Replicating Tables on page 77 provides more information. Dealing with Many-to-Many Relationships Where tables have many-to-many relationships, you have a choice of strategies for handling queries that need to join non-colocated data. Note: Joins are permitted only on data that is colocated. Query execution can be distributed and executed in parallel, but the joined rows in each partition member have to be restricted to other rows in the same partition. For tables have many-to-many relationships, choose one of the following strategies to handle queries that need to join non-colocated data: 58 vFabric SQLFire User's Guide Designing vFabric SQLFire Databases • Use parallel, data-aware procedures to run the logic for the query on the member that stores some or all of the data (to minimize data distribution hops). The procedure should execute multiple queries and then join the results using application code. Using Data-Aware Stored Procedures on page 163 provides more information. • Split the query into multiple queries, and perform the join in the application client code. Example: Adapting a Database Schema for SQLFire If you have an existing database design that you want to deploy to SQLFire, translate the entity-relationship model into a physical design that is optimized for SQLFire design principles. The goal is to identify tables to partition or replicate in the SQLFire cluster, and determine the partitioning key(s) for partitioned tables. This generally requires an iterative process to produce the most optimal design. Procedure 1. Read Guidelines for Adapting a Database to SQLFire on page 59and the preceding sections under Designing vFabric SQLFire Databases on page 57. 2. Evaluate data access patterns to define entity groups that are candidates for partitioning. See Step 1: Determine the entity groups on page 60. 3. Identify all tables in the entity groups. See Step 2: Identify the tables in each entity group on page 60. 4. Identify the "partitioning key" for each partitioned table. The partitioning key is the column or set of columns that are common across a set of related tables. See Step 3: Define the partitioning key for each group on page 61. 5. Identify the tables that are candidates for replication. You can replicate table data for high availability, or to co-locate table data that is necessary to execute joins. See Step 4: Identify replicated tables on page 61. Guidelines for Adapting a Database to SQLFire Follow these guidelines for designing a SQLFire database or adapting an existing database to SQLFire: • Focus your efforts on commonly-joined entities. Remember that all join queries must be performed on data that is co-located. In this release, SQLFire only supports joins where the data is co-located. Co-located data is also important for transaction updates, because the transaction can execute without requiring distributed locks in a multi-phase commit protocol. • After you locate commonly-joined entities, look for parent-child relationships in the joined tables. The primary key of a root entity is generally also the best choice for partitioning key. • Understand the trade-offs associated with different partitioning and co-location strategies. The steps that follow describe how to evaluate a customer order management system. This example shows tables from the Microsoft Northwind Traders sample database. 59 Managing Your Data in vFabric SQLFire Step 1: Determine the entity groups Entity groups are generally course-grained entities that have children, grand children, and so forth, and they are commonly used in queries. This example chooses these entity groups: Entity group Description Customer This group uses the customer identity along with orders and order details as the children. Product This group uses product details along with the associated supplier information. Step 2: Identify the tables in each entity group Identify the tables that belong to each entity group. In this example, entity groups use the following tables. Entity group Customer Tables Customers Orders Shippers 60 vFabric SQLFire User's Guide Designing vFabric SQLFire Databases Entity group Tables Order Details Product Product Suppliers Category Step 3: Define the partitioning key for each group In this example, the partitioning keys are: Entity group Partitioning key Customer CustomerID Product ProductID This example uses customerID as the partitioning key for the Customer group. The customer row and all associated orders will be collocated into a single partition. To explicitly colocate Orders with its parent customer row, use the colocate with clause in the create table statement: create table orders () partition by (customerID) colocate with (customers); Create the OrderDetails table in a similar fashion. In this way, SQLFire supports any queries that join any of Customer, Orders, and OrderDetails. This join query would be distributed to all partitions and executed in parallel, with the results streamed back to the client: select * from customer c , orders o where c.customerID = o.customerID; A query such as this would be pruned to the single partition that stores "customer100" and executed only on that SQLFire member: select * from customer c, orders o where c.customerID = o.customerID and c.customerID = 'customer100'; The optimization provided when queries are highly selective comes from engaging the query processor and indexing on a single member rather than on all partitions. With all customer data managed in memory, query response times are very fast. Consider how the above query would execute if the primary key was not used to partition the table. In this case, the query would be routed to each partition member where an index lookup would be performed, even though only a single member might have any data associated with the query. Finally, consider a case where an application needs to access customer order data for several customers: select * from customer c, orders o where c.customerID = o.customerID and c.customerID IN ('cust1', 'cust2', 'cust3'); Here, SQLFire prunes the query execution to only those partitions that host 'cust1', 'cust2', and 'cust3'. The union of the results is then returned to the caller. Step 4: Identify replicated tables If we assume that the number of categories and suppliers rarely changes, those tables can be replicated in the SQLFire cluster (replicated to all of the SQLFire members that host the entity group). If we assume that the Products table does change often and can be relatively large in size, then partitioning is a better strategy for that table. 61 Managing Your Data in vFabric SQLFire So for the product entity group, table Products is partitioned by ProductID, and the Suppliers and Categories tables are replicated to all of the members where Products is partitioned. Applications can now join Products, Suppliers and categories. For example: select * from Products p , Suppliers s, Categories c where c.categoryID = p.categoryID and p.supplierID = s.supplierID and p.productID IN ('someProductKey1', ' someProductKey2', ' someProductKey3'); In the above query, SQLFire prunes the query execution to only those partitions that host 'someProductKey1', ' someProductKey2', and ' someProductKey3.' 62 vFabric SQLFire User's Guide Chapter 10 Using Server Groups to Manage Data Use server groups to control where table data is stored. Server Groups Overview A server group specifies the SQLFire members that will host data for a table. You use a server group to logically group SQLFire data stores for managing a table's data. Any number of SQLFire members that host data can participate in one or more server groups. You specify named server groups when you start a SQLFire data store. 63 Managing Your Data in vFabric SQLFire A SQLFire member that is booted with host-data=false is an accessor and does not host table data, even if you specify one or more server groups. However, peer clients that host data can also participate in server groups. 64 vFabric SQLFire User's Guide Using Server Groups to Manage Data By default, all servers that host data are added to the "default" server group. Different logical database schema are often managed in different server groups. For example, an order management system might manage all customers and their orders in an "Orders" schema deployed to one server group. The same system might manage shipping and logistics data in a different server group. A single peer or server can participate in multiple server groups, typically as a way to colocate related data or to control the number of redundant copies in replicated tables. With support for dynamic group membership, the number of processes hosting data for a server group can change dynamically. However, this dynamic aspect of server group membership is abstracted away from the application developer, who can look at a server group as a single logical server. Server groups only determine those peers and servers where a table's data is being managed. Tables are always accessible for any peer member of the distributed system, and from thin clients that connect to a single server. When you invoke server side procedures, you can parallelize the execution of the procedure on all members in the server group. These data-aware procedures also execute on any peer clients that belong to the server groups. Without associating tables to specific member IP addresses, the capacity of a server group can be dynamically increased or decreased without any impact to existing servers or client applications. SQLFire can automatically rebalance the tables in the server group to the newly added members. Adding Members to Server Groups You define server group membership and/or create a server group when you start a SQLFire member using the server-groups boot property. 65 Managing Your Data in vFabric SQLFire For example, if you start a SQLFire server from the command line with sqlf, use the server-groups property to specify the names of one or more server groups that the server should join: sqlf server start -server-groups=OrdersDB,OrdersReplicationGrp,DBProcessInstance1 In this example, the SQLFire server participates in three server groups: OrdersDB, OrdersReplicationGrp and DBProcessInstance1. If this is the first SQLFire member to define a named server group, then SQLFire creates the group and adds the new member after startup. If other SQLFire members in the cluster were booted using the same server group, then SQLFire adds this new member to the existing group. If you specify no -server-groups property, then SQLFire automatically adds the data store member to the default server group. If you start a SQLFire peer client from within a Java application, specify the server-groups property as part of the JDBC peer client connection string. For example, use the connection URL: jdbc:sqlfire:;mcast-port=33666;host-data=true;server-groups=OrdersDB,OrdersReplicationGrp,DBProcessInstance1 Starting and Configuring SQLFire Servers on page 233 and Starting SQLFire Servers with the FabricServer Interface on page 119 provide more information about specifying boot properties. Assigning Tables to Server Groups When you create a new table, the CREATE TABLE statement can specify the server group to which the table belongs. A partitioned table is spread across all of the members of the specified server group. A replicated table is replicated to all members of the server group. See Replicating Tables on page 77. For example, the following command creates a replicated table on two server groups: CREATE TABLE COUNTRIES ( COUNTRY VARCHAR(26) NOT NULL, COUNTRY_ISO_CODE CHAR(2) NOT PRIMARY KEY, REGION VARCHAR(26), ) SERVER GROUPS (OrdersDB, OrdersReplicationGrp) Tables in SQLFire are replicated by default if you do not specify partitioning. If you do not specify one or more server group names, tables are partitioned or replicated across all members of the default server group for that schema. This behavior may not be desirable in all situations. For example, if the data in a replicated table changes frequently, the cost of maintaining a copy on each server in the default group may be prohibitive. In this case, the application developer or system administrator can have several members participate in a new, smaller server group to limit the number of replicas. When two tables are partitioned and colocated, it forces partitions that have the same values for those columns in the two tables to be located on the same member. Colocated tables must belong to at least one common server group. As a best practice, you deploy colocated tables on exactly the same server groups. See Partitioning Tables on page 67. 66 vFabric SQLFire User's Guide Chapter 11 Partitioning Tables Horizontal partitioning involves spreading a large data set (many rows in a table) across members in a cluster. SQLFire uses a variant of the consistent hash algorithm to help ensure that data is uniformly balanced across all members of the target server group. How Table Partitioning Works You specify the partitioning strategy of a table in the PARTITION BY clause of the CREATE TABLE statement. The available strategies include hash-partitioning on each row's primary key value, hash-partitioning on column values other than the primary key, range-partitioning, and list-partitioning. SQLFire maps each row of a partitioned table to a logical "bucket." The mapping of rows to buckets is based on the partitioning strategy that you specify. For example, with hash-partitioning on the primary key, SQLFire determines the logical bucket by hashing the primary key of the table. Each bucket is assigned to one or more members, depending on the number of copies that you configure for the table. Configuring a partitioned table with one or more redundant copies of data ensures that partitioned data remains available even if a member is lost. When members are lost or removed, the buckets are reassigned to new members based on load. Losing a member in the cluster never results in re-assigning rows to buckets. You can specify the total number of buckets to use with the BUCKETS Clause clause of the CREATE TABLE statement. The default number of buckets is 113. In SQLFire, all peer servers in a distributed system know which peers host which buckets, so they can efficiently access a row with at most one network hop to the member that hosts the data. Reads or writes to a partitioned table are transparently routed to the server that hosts the row that is the target of the operation. Each peer maintains persistent communication channels to every peer in the cluster. 67 Managing Your Data in vFabric SQLFire Figure 2: Partitioned Table Data Although each bucket is assigned to one or more specific servers, you can use a procedure to relocate buckets in a running system, in order to improve the utilization of resources across the cluster. See Rebalancing Partitioned Data on SQLFire Members on page 75. You can also pre-allocate buckets before loading data into the table, to ensure that imported data is evenly distributed among table partitions. See Pre-Allocating Buckets on page 75. Understanding Where Data Is Stored SQLFire uses a table's partitioning column values and the partitioning strategy to calculate routing values (typically integer values). It uses the routing values to determine the "bucket" in which to store the data. Each bucket is then assigned to a server, or to multiple servers if the partitioned table is configured to have redundancy. The buckets are not assigned when the table is started up, but occurs lazily when the data is actually put into a bucket. This allows you to start a number of members before populating the table. Note: If you intend to immediately load a new, partitioned table with data, use the SYS.CREATE_ALL_BUCKETS procedure to create the buckets before loading data. This best practice ensures that partitions are balanced even if you rapidly load data into the table using concurrent threads. 68 vFabric SQLFire User's Guide Partitioning Tables Figure 3: Partitioned Data in Buckets If you set the redundant-copies for the table to be greater than zero, SQLFire designates one of the copies of each bucket as the primary copy. All writes to the bucket go through the primary copy. This ensures that all copies of the bucket are consistent. The Group Membership Service (GMS) and distributed locking service ensure that all distributed members have a consistent view of primaries and secondaries at any moment in time across the distributed system, regardless of membership changes initiated by the administrator or by failures. Failure and Redundancy If you have redundant copies of a partitioned table, you can lose servers without loss of data or interruption of service. When a server fails, SQLFire automatically re-routes any operations that were trying to write to the failed member to the surviving members. SQLFire also attempts to re-route failed read operations to another server if possible. If a read operation returns only a single row, then transparent failover is always possible. However, if an operation returns multiple rows and the application has consumed one or more rows, then SQLFire cannot fail over if a server involved in the query happens goes offline before all the results have been consumed; in this case the application receives a SQLException with SQLState X0Z01. All applications should account for the possibility of receiving such an exception, and should manually retry the query if such a failure occurs.. Read operations are also retried if a server is unavailable when a query is performed. In this figure, M1 is reading table values W and Y. It reads W directly from its local copy and attempts to read Y from M3, which is currently offline. In this case, the read is automatically retried in another available member that holds a redundant copy of the table data. 69 Managing Your Data in vFabric SQLFire Creating Partitioned Tables You create a partitioned table on a set of servers identified by named server groups (or on the default server group if you do not specify a named server group). Clauses in the CREATE TABLE statement determine how table data is partitioned, colocated, and replicated across the server group. This topic focuses on the partitioning_clause in CREATE TABLE. The CREATE TABLE reference page describes all of the options in more detail. The partitioning_clause controls the location and distribution of data in server groups. Using server groups and colocation is important for optimizing queries, and it is essential for cross-table joins. This version of SQLFire does not support cross-table joins for non-colocated data, so you must choose the partitioning clause carefully to enable the joins required by your application. The partitioning clause can specify column partitioning, range partitioning, list partitioning, or expression partitioning: { { PARTITION BY { PRIMARY KEY | COLUMN ( column-name [ , column-name ]* ) } | 70 vFabric SQLFire User's Guide Partitioning Tables PARTITION BY RANGE ( column-name ) ( VALUES BETWEEN value AND value [ , VALUES BETWEEN value AND value ]* ) | PARTITION BY LIST ( column-name ) ( VALUES ( value [ , value ]* ) [ , VALUES ( value [ , value ]* ) ]* ) | PARTITION BY ( expression ) } [ COLOCATE WITH ( table-name [ , table-name ] * ) ] } [ [ [ [ REDUNDANCY integer-constant ] BUCKETS integer-constant ] MAXPARTSIZE integer-constant ] RECOVERYDELAY integer-constant ] Note: If the table has no primary key, then SQLFire generates a unique row ID that is uses for partitioning the data. SQLFire supports the partitioning strategies described below. Partitioning strategy Description Column partitioning The PARTITION BY COLUMN clause defines a set of column names to use as the basis for partitioning. As a short-cut, you can use PARTITION BY PRIMARY KEY to refer to the table's primary key column(s). SQLFire uses an internal hash function that typically uses the hashCode() method of the underlying Java type for the specified column. For multiple columns, the internal hash function uses the serialized bytes of the specified columns to compute the hash. Range partitioning The PARTITION BY RANGE clause specifies the ranges of a field that should be colocated. This ensures the locality of data for range queries and for cross-table joins. The lower limit of the range is inclusive and the upper limit is exclusive. It is not necessary for the ranges to cover the whole spectrum of possible values for the field. Values that are not covered by the range are automatically partitioned in the server group, but with no guarantee of locality for those values. List partitioning The PARTITION BY LIST clause specifies the set of values of a field that should be colocated to optimize queries and to support cross-table joins. It is not necessary to list all of the possible values for the field. Any the values that are not part of the list are automatically partitioned in the server group, but with no guarantee of locality for those values. Expression partitioning The PARTITION BY ( expression ) clause that includes an expression is a type of hash partitioning that uses the expression to specify the value on which to hash. The expression must only reference field names from the table. This allows rows to be colocated based on a function of their values. Partitioning Examples You can partition tables by, for example, column (such as customer name), expression, priority ranges, and status. 71 Managing Your Data in vFabric SQLFire Partition Based on Columns This statement creates a table that is partitioned by the "CustomerName" column. All rows with the same CustomerName are guaranteed to be colocated in the same process space. Here, the SERVER GROUPS clause determines the peers and servers that host data for the partitioned table. A server group is a subset of all the peers and servers that host data in the distributed system. CREATE TABLE Orders ( OrderId INT NOT NULL, ItemId INT, NumItems INT, CustomerName VARCHAR(100), OrderDate DATE, Priority INT, Status CHAR(10), CONSTRAINT Pk_Orders PRIMARY KEY (OrderId) ) PARTITION BY COLUMN ( CustomerName ) SERVER GROUPS ( OrdersDBServers); Partition Based on Ranges When you use the PARTITION BY RANGE clause, specify a column with multiple ranges of values to use for partitioning. The following example specifies partitioning based on three ranges of values for the "Priority" column: CREATE TABLE Orders ( OrderId INT NOT NULL, ItemId INT, NumItems INT, CustomerName VARCHAR(100), OrderDate DATE, Priority INT, Status CHAR(10), CONSTRAINT Pk_Orders PRIMARY KEY (OrderId) ) PARTITION BY RANGE ( Priority ) ( VALUES BETWEEN 1 AND 11, VALUES BETWEEN 11 AND 31, VALUES BETWEEN 31 AND 50 ); Partition Based on a List When you use the PARTITION BY LIST clause, specify a column name and one or more lists of column values to use for partitioning. The following example partitions the table based on three different lists of values for the "Status" column: CREATE TABLE Orders ( OrderId INT NOT NULL, ItemId INT, NumItems INT, CustomerName VARCHAR(100), OrderDate DATE, Priority INT, Status CHAR(10), CONSTRAINT Pk_Orders PRIMARY KEY (OrderId) 72 vFabric SQLFire User's Guide Partitioning Tables ) PARTITION BY LIST ( Status ) ( VALUES ( 'pending', 'returned' ), VALUES ( 'shipped', 'received' ), VALUES ( 'hold' ) ); Partition Based on an Expression Expression partitioning partitions a table by evaluating a SQL expression that you supply. For example, the following statement partitions the table based on the month of the OrderDate column, using the MONTH function as the SQL expression: CREATE TABLE Orders ( OrderId INT NOT NULL, ItemId INT, NumItems INT, CustomerName VARCHAR(100), OrderDate DATE, Priority INT, Status CHAR(10), CONSTRAINT Pk_Orders PRIMARY KEY (OrderId) ) PARTITION BY ( MONTH( OrderDate ) ); Colocating Related Rows from Multiple Tables The COLOCATE WITH clause specifies the tables with which the partitioned table must be colocated. Note: Tables that are referenced in the COLOCATE WITH clause must exist at the time you create the partitioned table. When two tables are partitioned on columns and colocated, it forces partitions having the same values for those columns in both tables to be located on the same SQLFire member. For example, with range or list partitioning, any rows that satisfy the range or list are colocated on the same member for all the colocated tables. When you specify the COLOCATE WITH clause, you must use the PARTITION BY clause to specify partition columns in the target tables in the same order using the same partitioning strategy (for example, with identical ranges). The columns must also be of the same type, not considering constraints. Any REDUNDANCY or BUCKETS clause must also be the same as the tables with which it is colocated. Note: In order for two partitioned tables to be colocated, the SERVER GROUPS clauses in both CREATE TABLE statements must be identical. In order for two replicated tables to be colocated, both tables must specify the same server groups or one table's server groups must be a subset of the other table's server groups. For example, if you create the partitioned table, "countries," as follows: CREATE TABLE COUNTRIES ( COUNTRY VARCHAR(26) NOT NULL CONSTRAINT COUNTRIES_UNQ_NM Unique, COUNTRY_ISO_CODE CHAR(2) NOT NULL CONSTRAINT COUNTRIES_PK PRIMARY KEY, REGION VARCHAR(26), CONSTRAINT COUNTRIES_UC CHECK (country_ISO_code = upper(country_ISO_code) ) ) PARTITION BY PRIMARY KEY 73 Managing Your Data in vFabric SQLFire You can colocate another table, "cities," using the command: CREATE TABLE CITIES ( CITY_ID INTEGER NOT NULL CONSTRAINT CITIES_PK Primary key, CITY_NAME VARCHAR(24) NOT NULL, COUNTRY VARCHAR(26) NOT NULL, AIRPORT VARCHAR(3), LANGUAGE VARCHAR(16), COUNTRY_ISO_CODE CHAR(2) CONSTRAINT COUNTRIES_FK REFERENCES COUNTRIES (COUNTRY_ISO_CODE) ) PARTITION BY COLUMN (COUNTRY_ISO_CODE) COLOCATE WITH (COUNTRIES) In this example, both "countries" and "cities" are partitioned using the COUNTRY_ISO_CODE column. Rows with the same COUNTRY_ISO_CODE value are colocated on the same SQLFire members. See the CREATE TABLE reference page for more information. Making a Partitioned Table Highly Available Use the REDUNDANCY clause to specify a number of redundant copies of a table for each partition to maintain. Because SQLFire is primarily a memory-based data management system, it is important to use redundancy when necessary to enable fail-over if a member shuts down or fails. However, keep in mind that maintaining a large number of redundant copies has an adverse impact on performance, network usage, and memory usage. A REDUNDANCY value of 1 is recommended to maintain a secondary copy of the table data. For example: CREATE TABLE COUNTRIES ( COUNTRY VARCHAR(26) NOT NULL, COUNTRY_ISO_CODE CHAR(2) NOT PRIMARY KEY, REGION VARCHAR(26), ) REDUNDANCY 1 SQLFire attempts to place copies of the same bucket onto hosts that have different IP addresses if possible, to protect against machine failure. However, if there is only one machine available SQLFire places multiple copies on that machine. Setting the enforce-unique-host boot property prevents SQLFire from ever placing multiple copies on the same machine. Set the redundancy-zone boot property to ensure that SQLFire places redundant copies on specific zones that you define. For example, to ensure that redundant copies are placed on different racks, set the redundancy-zone for each machine to the logical name of the rack on which the machine runs. See Configuration Properties on page 327. If the primary and secondary buckets for a partition are unavailable, then queries to the table can fail. For a persistent table, queries involving missing buckets fail with a PartitionOfflineException. Queries across the entire table would also fail. Queries to non-persistent tables with missing partitions can return empty results. Limiting the Memory Consumption on a Member Use the MAXPARTSIZE clause of the CREATE TABLE statement to load- balance partitioned data among the available members. The MAXPARTSIZE ClauseExample with BUCKETS, RECOVERYDELAY, and MAXPARTSIZE clause specifies the maximum memory for any partition on a SQLFire member. 74 vFabric SQLFire User's Guide Partitioning Tables Pre-Allocating Buckets As a best pratice, use the SYS.CREATE_ALL_BUCKETS procedure to create the buckets for a partitioned table before you begin loading data. SYS.CREATE_ALL_BUCKETS immediately creates the necessary buckets on datastores for partitioned tables. (Normally SQLFire assigns buckets to servers lazily, as inserts are executed against the table.) Pre-allocating the buckets ensures that partitioned table data is evenly distributed in the cluster. If you do not use SYS.CREATE_ALL_BUCKETS, data can become skewed if you rapidly load table data using concurrent processes. If a partitioned table becomes skewed, use SYS.REBALANCE_ALL_BUCKETS to rebalance all partitioned table data in the distributed system. Rebalancing Partitioned Data on SQLFire Members You can use rebalancing to dynamically increase or decrease your SQLFire cluster capacity, or to improve the balance of data across the distributed system. Rebalancing is a SQLFire member operation that affects partitioned tables created in the cluster. Rebalancing performs two tasks: • If the a partitioned table's redundancy setting is not satisfied, rebalancing does what it can to recover redundancy. See Making a Partitioned Table Highly Available on page 74. • Rebalancing moves the partitioned table's data buckets between host members as needed to establish the best balance of data across the distributed system. For efficiency, when starting multiple members, trigger the rebalance a single time, after you have added all members. Note: If you have transactions running in your system, be careful in planning your rebalancing operations. Rebalancing may move data between members, which could cause a running transaction to fail with a TransactionDataRebalancedException. Start a rebalance operation using one of the following options: • At the command line when you boot a SQLFire server: sqlf server start -rebalance • Eexecuting a system procedure in a running SQLFire member: call sys.rebalance_all_buckets(); This procedure initiates rebalancing of buckets across the entire SQLFire cluster for all partitioned tables. How Partitioned Table Rebalancing Works The rebalancing operation runs asynchronously. As a general rule, rebalancing takes place on one partitioned table at a time. For tables that have colocated data, rebalancing works on the tables as a group, maintaining the data colocation between the tables. You can continue to access partitioned tables while rebalancing is in progress. Queries, DML operations, and procedure executions continue while data is moving. If a procedure executes on a local data set, you may see a performance degradation if that data moves to another member during procedure execution. Future invocations are routed to the correct member. For tables that are configured with expiration based on idle time, the rebalancing operation resets the last accessed time of the table entries on buckets that are moved. 75 Managing Your Data in vFabric SQLFire When to Rebalance a Partitioned Table You typically want to trigger rebalancing when overall capacity is increased or reduced through member startup, shut down or failure. You may also need to rebalance when you use partitioned table redundancy for high availability, and you have configured your table to not automatically recover redundancy after a SQLFire member fails (the default RECOVERYDELAY setting). In this case, SQLFire only restores redundancy when you invoke a rebalance operation. See Making a Partitioned Table Highly Available on page 74. Managing Replication Failures SQLFire uses multiple failure detection algorithms to detect replication problems quickly. SQLFire replication design focuses on consistency, and does not allow suspect members or network-partitioned members to operate in isolation. Configuring suspect-member Alerts When any member of the distributed system fails, it is important for other services to detect the loss quickly and transition application clients to other members. Any peer or server in the cluster can detect a problem with another member of the cluster, which initiates "SUSPECT" processing with the membership coordinator. The membership coordinator then determines whether the suspect member should remain in the distributed system or should be removed. Use the ack-wait-threshold property to configure how long a SQLFire peer or server waits to receive an acknowledgment from other members that are replicating a table's data. The default value is 15 seconds; you specify a value from 0 to 2147483647 seconds. After this period, the replicating peer sends a severe alert warning to other members in the distributed system, raising a "suspect_member" alert in the cluster. To configure how long the cluster waits for this alert to be acknowledged, set the ack-severe-alert-threshold property. The default value is zero, which disables the property. How Replication Failure Occurs Failures during replication can occur in the following ways: • A replica fails before sending an acknowledgment. The most common failure occurs when a member process is terminated during replication. When this occurs, the TCP connection from all members is terminated, and the membership view is updated quickly to reflect the change. The member who initiated replication continues replicating to other members. If instead of terminating, the process stays alive (but fails to respond) the initiating member waits for a period of time and then raises an alert with the distributed system membership coordinator. The membership coordinator evaluates the health of the suspect member based on heartbeats and health reports from other members in the distributed system. The coordinator may decide to evict the member from the distributed system, in which case it communicates this change in the membership view to all members. At this point, the member that initiated replication proceeds and completes replication using available peers and servers. In addition, clients connected to this member are automatically re-routed to other members. • An "Owning" member fails. If the designated owner of data for a certain key fails, the system automatically chooses another replica to become the owner for the key range that the failed member managed. The updating thread is blocked while this transfer takes place. If at least one replica is available, the operations always succeeds from the application's viewpoint. 76 vFabric SQLFire User's Guide Chapter 12 Replicating Tables SQLFire server groups control which SQLFire data store members replicate the table's data. SQLFire replicates table data both when a new table is initialized in a cluster and when replicated tables are updated. How SQLFire Replicates Tables SQLFire replicates every single row of a replicated table synchronously to each table replica in the target server group(s). With synchronous replication, table reads can be evenly balanced to any replica in the cluster, with no single member becoming a contention point. SQLFire replicates data to all peers in the server groups where the table was created. Replication occurs in parallel to other peers over a TCP channel. SQLFire replicates table data both when a new table is initialized in a cluster and when replicated tables are updated. Replication at Initialization When a non-persistent ("memory only") replicated table is created in a peer or server, it initializes itself using data from another member of the server group that hosts the table. A single data store member in the server group is chosen, and data for the table is streamed from that member to initialize the new replica. If the selected member fails during the replication process, the initializing process selects a different member in the server group to stream the data. Replication During Updates When an application updates a replicated table, SQLFire distributes the update to all replicas in parallel, utilizing the network bandwidth between individual members of the cluster. The sending peer or server locks the updated row locally, and then distributes the update to the replicas. After each of the replicas processes the update and responds with an acknowledgment message, the originating SQLFire peer returns control to the application. The update process is conservative in order to ensure that all copies of a replicated table contain consistent data. Each receiver processes the update entirely, applying constraint checks if necessary and updating the local table data, before responding with an acknowledgment. Each operation on a single row key is performed atomically per replica, regardless of how many columns are being read or updated. Deciding When to Use Replicated Tables Code tables are often good candidates for replication. Application data is frequently normalized to maintain "code" fields in "fact" tables, and to maintain the details associated with each "code" in an associated "dimension" table. Code tables are often small and change infrequently, but they are frequently joined with their parent "fact" table in queries. Code tables of this sort are good candidates for using replicated tables. 77 Managing Your Data in vFabric SQLFire Also note that this version of SQLFire supports joins only on co-located data. Instead of using partitioning in all cases, you should consider having applications replicate smaller tables that are joined with other partitioned tables. Note: If multiple applications update the same row of a replicated table at the same time outside of a transaction, the table data can become out of sync when SQLFire replicates those updates. Keep this limitation in mind when using replicated tables. Creating Replicated Tables You can create replicated tables explicitly or by default, using CREATE TABLE statement. SQLFire creates a replicated table by default when you execute a CREATE TABLE on page 505 statement and you do not include a PARTITIONING clause. You can also explicitly create a replicated table using the REPLICATE clause in the CREATE TABLE statement. For example: CREATE TABLE COUNTRIES ( COUNTRY VARCHAR(26) NOT NULL CONSTRAINT COUNTRIES_UNQ_NM Unique, COUNTRY_ISO_CODE CHAR(2) NOT NULL CONSTRAINT COUNTRIES_PK PRIMARY KEY, REGION VARCHAR(26), CONSTRAINT COUNTRIES_UC CHECK (country_ISO_code = upper(country_ISO_code) ) ) REPLICATE; Because this command omits the SERVER GROUPS clause, the example creates the 'countries' table and replicates it on members of the cluster that host data (all peers and servers in the default server group that set the host-data property to true). 78 vFabric SQLFire User's Guide Chapter 13 Estimating Memory Requirements Designing a SQLFire database also involves estimating the memory requirements for your data based on the size of the actual table values and indexes, the overhead that SQLFire requires for your data, and the overall usage pattern for your data. You can estimate the memory requirements for tables using general guidelines for SQLFire overhead. Or, you can load tables with representative data and then query the SQLFire SYS.MEMORYANALYTICS table to obtain details about the memory required for individual tables and indexes. Estimating SQLFire Overhead SQLFire requires different amounts of overhead per table and index entry depending on whether you persist table data or configure tables for overflow to disk. Add these overhead figures to the estimated size of each table or index entry to provide a rough estimate for your data memory requirements. If you already have representative data, use the SQLFire Java agent to query the SYS.MEMORYANALYTICS table to obtain a more accurate picture of the memory required to store your data. Note: All overhead values are approximate. Be sure to validate your estimates in a test environment with representative data. Table 1: Approximate Overhead for SQLFire Table Entries Table is persisted? Overflow is configured? Approximate overhead No No 64 bytes Yes No 120 bytes Yes Yes 152 bytes Table 2: Approximate Overhead for SQLFire Index Entries Type of index entry Approximate overhead New index entry 80 bytes First non-unique index entry 24 bytes Subsequent non-unique index entry 8 bytes to 24 bytes* *If there are more than 100 entries for a single index entry, the overhead per entry increases from 8 bytes to approximately 24 bytes. 79 Managing Your Data in vFabric SQLFire Viewing Memory Usage in SYS.MEMORYANALYTICS SQLFire includes instrumentation to display the memory used by individual tables and indexes in a SQLFire member. You can view this memory usage information by starting a Java agent process when you boot SQLFire members, and then querying the SYS.MEMORYANALYTICS virtual table from a client connection. Enabling SYS.MEMORYANALYTICS Follow this procedure to enable the SYS.MEMORYANALYTICS virtual table. Prerequisites • Create an evaluation SQLFire distributed system to determine the memory footprint for your data. Do not enable memory analytics on a production system. • You must have representative table data and index entries in order to accurately evaluate the memory footprint. Create the necessary SQL scripts to automate creating your schema and loading data into your tables. • Consider using fewer SQLFire members in the evaluation system to simplify the evaluation process. • If your SQLFire distributed system uses locators for member discovery, be sure to enable the Java agent on the locator as well as the data store members. Although a locator does not generally host data, you can use the locator data to compare data memory footprints with non-data memory footprints. Procedure Follow these steps to start a SQLFire member with the Java agent to provide memory analytics: 1. Use the -javaagent: jar_path Java system property to specify the sqlfire.jar file in your installation when you start each SQLFire member. For example, if you use sqlf to start a SQLFire server: sqlf server start -client-address=1527 -J-javaagent:c:\vFabric_SQLFire_11_bNNNNN\lib\sqlfire.jar Specify the complete path and filename of sqlfire.jar for your system. If you use a locator for member discovery, also use the -javaagent: jar_path system property when starting the locator. 2. If your schema and data are not already available in the SQLFire system (as persisted data), run any necessary SQL scripts to create the schema and load table data. For example: cd c:\vFabric_SQLFire_11_bNNNNN\quickstart sqlf sqlf> connect client 'localhost:1527'; sqlf> run 'create_colocated_schema.sql'; sqlf> run 'loadTables.sql'; 3. Connect to SQLFire and query the SYS.MEMORYANALYTICS table to view the memory usage information: sqlf sqlf> connect client 'localhost:1527'; sqlf> select * from sys.memoryanalytics; SQLENTITY |ID |MEMORY ---------------------------------------------------------------APP.FLIGHTS (Entry Size, Value Size, Row Count) |dyozie-e4310(6880):3439/59731 |30352,31436,542 AAP.FLIGHTS.DESTINDEX (Index Entry Overhead, SkipList Size, Max& |dyozie-e4310(6880):3439/59731 |2104,696,3 (2803 = 2.74 kb) 80 vFabric SQLFire User's Guide Estimating Memory Requirements APP.FLIGHTS.DESTINDEX (Index Entry Size, Value Size, Row Count) |dyozie-e4310(6880):3439/59731 |4888,3784,87 [...] Understanding Table and Index Values Querying the SYS.MEMORYANALYTICS table provides run-time information about the tables and indexes available in SQLFire. Table Values Each table has a single row in SYS.MEMORYANALYTICS identitfied with the SQLENTITY format: schema_name.table_name (Entry Size, Value Size, Row Count). The ID column value displays the values separated by commas. Table Value Description Entry Size The per-entry overhead, in bytes. (This excludes the Value Size below.) Value Size The total size of a table row, in bytes. (This includes the Entry Size overhead.) Row Count The total number of rows stored on the local SQLFire member. For a partitioned table, this includes all buckets for the table, as well as primary and secondary replicas. For example, the following row from SYS.MEMORYANALYTICS shows that the APP.FLIGHTS table has 30352 bytes of overhead per row, with 542 total rows: SQLENTITY |ID |MEMORY ---------------------------------------------------------------APP.FLIGHTS (Entry Size, Value Size, Row Count) |dyozie-e4310(6880):3439/59731 |30352,31436,542 Index Values Each index has two rows in SYS.MEMORYANALYTICS. The first row uses the SQLENTITY format: schema_name.table_name.index_name (Index Entry Overhead, SkipList Size, Max Level). This row provides details about concurrent skip lists for the index. The ID column value displays these values separated by commas: Index Value Description Index Entry Overhead The number of linked list objects that the index uses for storing the entry. SkipList Size The number of linked list objects that the index uses for skipping values to expedite searches. Max Level The total number of skip lists that are currently available for lookups. 81 Managing Your Data in vFabric SQLFire For example, the following row from SYS.MEMORYANALYTICS shows that APP.FLIGHTS.DESTINDEX uses 2803 bytes for skip lists: SQLENTITY |ID |MEMORY ---------------------------------------------------------------APP.FLIGHTS.DESTINDEX (Index Entry Overhead, SkipList Size, Max& |dyozie-e4310(6880):3439/59731 |2104,696,3 (2803 = 2.74 kb) The second row for an index uses the SQLENTITY format: schema_name.table_name.index_name (Index Entry Size, Value Size, Row Count). This row provides information similar to the values for a table entry. The ID column value displays these values separated by commas: Index Value Description Index Entry Size The per-index overhead, in bytes. (This includes the Index Entry Overhead from the previous table, but excludes the Value Size below.) Value Size The size of the data structure used to point to the underlying region entries, in bytes. For a unique index, this corresponds to the size of a pointer reference. Row Count The total number of entries in the index. For example, the following row from SYS.MEMORYANALYTICS shows that APP.FLIGHTS.DESTINDEX has 4888 bytes of overhead with 87 index entries: SQLENTITY |ID |MEMORY ---------------------------------------------------------------APP.FLIGHTS.DESTINDEX (Index Entry Size, Value Size, Row Count) |dyozie-e4310(6880):3439/59731 |4888,3784,87 Displaying the Total Memory Footprint You can query SYS.MEMORYANALYTICS with an optmizer hint to display the complete memory footprint of tables and indexes. Use the sizerHints=withMemoryFootPrint hint with your query to display the memory footprint: SELECT * FROM sys.memoryAnalytics -- SQLFIRE-PROPERTIES sizerHints=withMemoryFootPrint ; Note: When processing a SQL script file, SQLFire does not recognize the terminating semicolon character if it appears at the end of a SQL comment line. For this reason, you must place the terminating semicolon on a separate line by itself, if the optmizer hint extends to the end of the statement. When you include this optimizer hint, the query displays an additional row for each table and index, summarizing the memory footprint for the SQLFire, GemFire, and other components. For example: SQLENTITY |ID |MEMORY ---------------------------------------------------------------[...] 82 vFabric SQLFire User's Guide Estimating Memory Requirements APP.FLIGHTS (sqlfire,gemfire,others) |dyozie-e4310(6880):3439/59731 |12912,299736,680704 (993352 = 970.07 kb) APP.FLIGHTS.DESTINDEX (sqlfire,gemfire,others) |dyozie-e4310(6880):3439/59731 |5072,0,3288 (8360 = 8.16 kb) [...] 83 Chapter 14 Using Disk Stores to Persist Data By default, a SQLFire distributed system persists only the data dictionary for the tables and indexes you create. These persistence files are stored in the datadictionary subdirectory of each locator and data store that joins the distributed system. Table data, however, is not persisted by default; if you shut down al SQLFire members, the tables are empty on the next startup. You have the option to persist table data to disk as a backup of the in-memory copy, or to overflow table data to disk when memory use gets too high. Overview of Disk Stores The two disk store options, overflow and persistence, can be used individually or together. Overflow uses disk stores as an extension of in-memory table management for both partitioned and replicated tables. Persistence stores a redundant copy of all table data managed in a peer. See Evicting Table Data from SQLFire on page 197 for more information about configuring tables to overflow to disk. Data Types for Disk Storage Disk storage is available for these data types: • Table data. Persist and/or overflow table data managed in SQLFire peers. • Gateway sender queues. Persist gateway sender queues for high availability in a WAN deployment. These queues always overflow. • AsyncEventListener and DBSynchronizer queues. Persist these queues for high availability. These queues always overflow, and can be persistent. You can store data from multiple tables and queues in a single disk store. Creating Disk Stores and Using the Default Disk Store You create named disk stores in the data dictionary using the CREATE DISKSTORE DDL statement. Individual tables can then specify named disk stores in their CREATE TABLE DDL statements to use the stores for persistence and/or overflow. You can store data from multiple tables and queues in the same named disk store. See Guidelines for Designing Disk Stores on page 91. Tables that do not name a disk store but specify persistence or overflow in their CREATE TABLE statement use the default disk store. The location of the default diskstore is determined by the value of the sys-disk-dir boot property. The default disk store is named SQLF-DEFAULT-DISKSTORE. Gateway sender queues, AsyncEventListener queues, and DBSynchronizer queues can also be configured to use a named disk store. The default disk store is used if you do not specify a named disk store when creating the queue. See CREATE GATEWAYSENDER on page 498 or CREATE ASYNCEVENTLISTENER on page 490. 85 Managing Your Data in vFabric SQLFire Peer Client Considerations for Persistent Data Peer clients (clients started using the host-data=false property) do not use disk stores and can never persist the SQLFire data dictionary. Instead, peer clients rely on other data stores or locators in the distributed system for persisting data. If you use a peer client to execute DDL statements that require persistence and there are no data stores available in the distributed system, SQLFire throws a data store unavailable exception (SQLState: X0Z08). You must start locators and data stores before starting peer clients in your distributed system. If you start a peer client as the first member of a distributed system, the client initializes an empty data dictionary for the distributed system as a whole. Any subsequent datastore that attempts to join the system conflicts with the empty data dictionary and fails to start with a ConflictingPersistentDataException. Shared-Nothing Disk Store Design Individual SQLFire peers that host table data manage their own disk store files, completely separate from the disk stores files of any other member. When you create a disk store, you can define certain properties that specify where and how each SQLFire peer should manages disk store files on their local filesystem. SQLFire supports persistence for replicated and partitioned tables. The disk store mechanism is designed for locally-attached disks. Each peer manages its own local disk store, and does not share any disk artifacts with other members of the cluster. This shared nothing design eliminates the process-level contention that is normally associated with traditional clustered databases. Disk stores use rolling, append-only log files to avoid disk seeks completely. No complex B-Tree data structures are stored on disk; instead SQLFire always assumes that complex query navigation is performed using in-memory indexes. Disk stores also support the SQLFire data rebalancing model. When you increase or decrease capacity by adding or removing peers in a cluster, the disk data also relocates itself as necessary. What SQLFire Writes to the Disk Store For each disk store, SQLFire stores detailed information about related members and tables. SQLFire stores these items in each disk store: • List of members that host the store and information on their status, such as running or offline and time stamps. • List of tables that use the disk store. For each table in the disk store, SQLFire stores: • Configuration attributes pertaining to loading and capacity management, used to load the data quickly on startup. • Table DML operations. Disk Store State Disk store access and management differs according to whether the store is online or offline. When a member shuts down, its disk stores go offline. When the member starts up again, its disk stores come back online in the SQLFire cluster. • Online, a disk store is owned and managed by its member process. • Offline, the disk store is simply a collection of files in your host file system. The files are open to access by anyone with the right file system permissions. You can copy the files using your file system commands, for backup or to move your member’s disk store location. You can also run maintenance operations on the offline disk store, like file compaction and validation using the sqlf utility. Note: The files for a disk store are used by SQLFire as a group. Treat them as a single entity. If you copy them, copy them all together. Do not change the file names or permissions. 86 vFabric SQLFire User's Guide Using Disk Stores to Persist Data When a disk store is offline, its data is unavailable to the SQLFire distributed system. For partitioned tables, the data is split between multiple members, so you can access the offline data only if you store replicas of the partitioned table on other members of the cluster. Disk Store Directories When you create a disk store, optionally specify the location of directories where sqlf stores persistence-related files. sqlf generates disk store artifacts in a directory that it chooses in the following order: 1. If you provide absolute directory paths, sqlf uses the paths as-is. You must ensure that the proper directory structure exists. 2. If you provide relative directory paths, or you do not specify any directories, then the path resolution is done in this order: 1. If the sys-disk-dir boot property specifies a directory, the disk store path is resolved relative to that directory or is used as the directory for persistence. 2. If sys-disk-dir is not set, SQLFire uses the directory from which the system was started (the current directory) for path resolution, or it uses that directory as the persistence directory. Disk Store Persistence Attributes SQLFire persists data on disk stores in synchronous or asynchronous mode. You configure the persistence mode for a table in the CREATE TABLE statement, while attributes to control asynchronous persistence are configured in the CREATE DISKSTOREstatement. In synchronous mode, SQLFire writes each DML operation to the OS buffer as part of the statement execution. This mode provides greater reliability than asynchronous mode, but with lower performance. In asynchronous mode, SQLFire batches DML statements before flushing them to the OS buffers. This is faster than synchronous mode, but batch operations may be lost if a failure occurs. (You can use redundancy to ensure that updates are successfully logged on another machine.) In asynchronous mode, you can control the frequency of flushing batches by setting the following attributes when you create a named disk store: • QUEUESIZE sets the number of affected rows that can be asynchronously queued. After this number of pending rows are queued, operations begin blocking until some of the modified, created, or deleted rows are flushed to disk. • TIMEINTERVAL sets the number of milliseconds that can elapse before queued data is flushed to disk. See CREATE DISKSTORE on page 494 Note: Always start all SQLFire servers and peer processes that host data on disk in parallel. A SQLFire process with persistent data may wait for other processes to startup first to guarantee consistency. Always use the shutdown-all command to gracefully shut down a cluster. This allows each member to reach a consistent replication state and record that state with other replicas in the cluster. When you restart peers after a graceful shutdown, each member can recover in parallel without waiting for others to provide consistent replication data. Disk Store File Names and Extensions Disk store files include store management and access control files and the operation log, or oplog, files, consisting of one file for deletions and another for all other operations. The next table describe file names and extensions; they are followed by example disk store files. 87 Managing Your Data in vFabric SQLFire File Names File names have three parts. First Part of File Name: Usage Identifier Usage Identifier Values Usage Examples OVERFLOW Oplog data from overflow tables and queues OVERFLOWoverflowDS1_1.crf only. BACKUP Oplog data from persistent and persistent+overflow tables and queues. BACKUPoverflowDS1.if, BACKUPSQLF-DEFAULT-DISKSTORE.if DRLK_IF Access control - locking the disk store. DRLK_IFoverflowDS1.lk, DRLK_IFSQLF-DEFAULT-DISKSTORE.lk Second Part of File Name: Disk Store Name Disk Store Name Values Usage Examples Non-default disk stores. name="OVERFLOWDS1" DRLK_IFOVERFLOWDS1.lk, name="PERSISTDS1" BACKUPPERSISTDS1_1.crf Note: SQLFire internally converts and uses disk store names in upper case characters, even if you specify lower case characters in the DDL statement. SQLF-DEFAULT-DISKSTORE Default disk store name, used when persistence or overflow are specified on a table or queue but no disk store is named. DRLK_IFSQLF-DEFAULT-DISKSTORE.lk, BACKUPSQLF-DEFAULT-DISKSTORE_1.crf SQLF-DD-DISKSTORE Default disk store for persisting the data dictionary. BACKUPSQLF-DD-DISKSTORE_1.crf Third Part of File Name: oplog Sequence Number oplog Sequence Number Usage Examples Sequence number in the format _n Oplog data files only. Numbering starts with OVERFLOWoverflowDS1_1.crf, 1. BACKUPpersistDS1_2.crf, BACKUPpersistDS1_3.crf File Extensions 88 File Extension Values Usage Notes if Disk store metadata Stored in the first disk-dir listed for the store. Negligible size - not considered in size control. lk Disk store access control Stored in the first disk-dir listed for the store. Negligible size - not considered in size control. vFabric SQLFire User's Guide Using Disk Stores to Persist Data File Extension Values Usage Notes crf Oplog: create, update, and invalidate operations Pre-allocated 90% of the total max-oplog-size at creation. drf Oplog: delete operations Pre-allocated 10% of the total max-oplog-size at creation. krf Oplog: key and crf offset information Created after the oplog has reached the max-oplog-size. Used to improve performance at startup. Disk Store Operation Logs At creation, each operation log is initialized at the disk store's MAXLOGSIZE value, with the size divided between the crf and drf files. SQLFire only truncates the unused space on a clean shutdown (for example, sqlf server stop or sqlf shut-down-all). After the oplog is closed, SQLFire also attempts to created a krf file, which contains the key names as well as the offset for the value within the crf file. Although this file is not required for startup, if it is available, it will improve startup performance by allowing SQLFire to load the entry values in the background after the entry keys are loaded. See When an operation log is full, SQLFire automatically closes it and creates a new log with the next sequence number. This is called oplog rolling. Note: Log compaction can change the names of the disk store files. File number sequencing is usually altered, with some existing logs removed or replaced by newer logs with higher numbering. SQLFire always starts a new log at a number higher than any existing number. The system rotates through all available disk directories to write its logs. The next log is always started in a directory that has not reached its configured capacity, if one exists. When Disk Store oplogs Reach the Configured Disk Capacity If no directory exists that is within its capacity limits, how SQLFire handles this depends on whether automatic compaction is enabled. • If AUTOCOMPACT is enabled (set to 'true), SQLFire creates a new oplog in one of the directories, going over the limit, and logs a warning that reports: Even though the configured directory size limit has been exceeded a new oplog will be created. The current limit is of XXX. The current space used in the directory is YYY. Note: When auto-compaction is enabled, directory sizes do not limit how much disk space is used. SQLFire performs auto-compaction, which should free space, but the system may go over the configured disk limits. • If auto-compaction is disabled, SQLFire does not create a new oplog. DML operations to tables block, and SQLFire logs the error: Disk is full and rolling is disabled. No space can be created Factors Contributing to High Disk Throughput SQLFire disk store design contains several factors that contribute to very high disk throughput. They include pooling, avoiding seeks, and buffered logging. 89 Managing Your Data in vFabric SQLFire Pooling Each SQLFire member manages its own disk store, and no disk contention exists between processes. Each partition can manage its data on local disks. If the application "write" load can be uniformly balanced across the cluster, the aggregate disk throughput is equal to the disk transfer rate time the number of partitions, assuming a single disk per partition. Disk transfer rates can be up to 100MB/sec on commodity machines today. Avoiding Seeks Random access on disk, which causes disk heads to seek for hundreds of concurrent thread, is probably the single biggest reason why traditional databases do not scale. Average disk seek times today are still 2ms or higher. SQLFire manages most (or all) of the data in cluster memory, and all reads are served without navigating through BTree-based indexes and data files on disk. This is the case when data is persistent. Note, however, that in overflow-only mode, data files on disk are accessed as necessary. Buffered Logging When writes do occur, SQLFire simply logs the operations to disk in "append-only" oplog files. By appending, SQLFire can continuously write to consecutive sectors on disk without requiring disk head movement. SQLFire flushes writes to the OS buffer rather than 'fsync' all the way to disk. The writes are buffered by the IO subsystem in the kernel, which allows the IO scheduler to merge and sort disk writes to achieve the highest possible disk throughput. Write requests need not initiate any disk I/O until some time in the future. Thus, from the perspective of a user application, write requests stream at much higher speeds, unencumbered by the performance of the disk. Risk of data loss due to sudden failures at a hardware level are mitigated by having multiple members writing in parallel to disk. In fact, it is assumed that hardware will fail, especially in large clusters and data centers, and that software needs to take these failures into account. The SQLFire system is designed to recover in parallel from disk and to guarantee data consistency when data copies on disk do not 90 vFabric SQLFire User's Guide Using Disk Stores to Persist Data agree with each other. Each member of the distributed system logs membership changes to its persistent files and uses this information during recovery to determine the replica that has the latest changes, and members automatically synchronize these changes at startup. Guidelines for Designing Disk Stores Work with your system designers and developers to plan for disk storage requirements in testing and production database systems. Work with host system administrators to determine where to place your disk store directories on each peer computer. Consider these guidelines when designing disk stores: • Tables can be overflowed, persisted, or both. For efficiency, place table data that is overflowed on one disk store with a dedicated physical disk. Place table data that is persisted, or persisted and overflowed, on another disk store with on a different physical disk. For example, gateway sender, AsyncEventListener, and DBSynchronizer queues are always overflowed and may be persisted. Assign them to overflow disk stores if you do not persist, and to persistence disk stores if you do. Ensure that each disk store resides on a separate physical disk, for best performance. • When calculating your disk requirements, consider your table modification patterns and compaction strategy. SQLFire creates each oplog file at the specified MAXLOGSIZE. Obsolete DML operations are only removed from the oplogs during compaction, so you need enough space to store all operations that are done between compactions. For tables where you are doing a mix of updates and deletes, if you use automatic compaction, a good upper bound for the required disk space is (1 / (1 - (compaction_threshold/100)) ) * data size where data size is the total size of all the table data you store in the disk store. So, for the default COMPACTIONTHRESHOLD of 50, the disk space is roughly twice your data size. The compaction thread could lag behind other operations, causing disk use to rise above the threshold temporarily. If you disable automatic compaction, the amount of disk required depends on how many obsolete operations accumulate between manual compactions. • Based on your anticipated disk storage requirements and the available disks on your host systems: • Make sure the new storage does not interfere with other processes that use disk on your systems. If possible, store your files to disks that are not used by other processes, including virtual memory or swap space. If you have multiple disks available, for the best performance, place one directory on each disk. • Use different directories for different peers that run on the same computer. You can use any number of directories for a single disk store. • Choose disk store names that reflect how the stores should be used and that work for your operating systems. Disk store names are used in the disk file names: • Use disk store names that satisfy the file naming requirements for your operating system. For example, if you store your data to disk in a Windows system, your disk store names could not contain any of these reserved characters, < > : " / \ | ? *. • Do not use very long disk store names. The full file names must fit within your operating system limits. On Linux, for example, the standard limitation is 255 characters. • Create each disk store with CREATE DISKSTORE before you create persistent or overflow tables. • You may choose to parallelize disk access for oplog and overflow files using by targeting disk store files to multiple logical disk partitions. • SQLFire disk store files must be highly available. Back up disk store files on a regular schedule, either by copying the files while the system is offline, or by using the sqlf backup command to perform online backups. SQLFire peers in the cluster manage their local disk stores using the properties you specify in the CREATE DISKSTORE statement. After you create named disk stores, you can create tables that persist or overflow their data to disk stores. 91 Managing Your Data in vFabric SQLFire Related Topics CREATE DISKSTORE on page 494 CREATE TABLE on page 505 Persist Table Data to a Disk Store on page 92 Evicting table data from memoryUse eviction to remove table data from memory, or to persist the overflow data in a disk store. Creating a Disk Store or Using the Default You can create a disk store for persistence and/or overflow or use the default disk store. Data from multiple tables can be stored in the same disk store. Default Disk Stores Tables that do not name a disk store but specify persistence or overflow in their CREATE TABLE statement are automatically assigned to the default disk store, SQLF-DEFAULT-DISKSTORE. Also, gateway, AsyncEventListener, and DBSynchronizer queues always use the default disk store. The default diskstore is saved to the SQLFire data store's working directory, unless you change the value of the sys-disk-dir boot property to specify another location. Note: SQLFire locator and data store members also create disk store files in order to persist the data dictionary for the tables and indexes created the SQLFire distributed system. These persistence files are stored in the datadictionary subdirectory of each locator and data store that joins the distributed system. The data dictionary is always persisted, regardless of whether you configure data persistence or overflow for individual tables. Table data is not persisted by default; if you shut down al SQLFire members, the tables are empty on the next startup. Never move or modify the datadictionary subdirectory or the associated disk store files in datadictionary. If the data dictionary of a SQLFire locator or data store member is unavailable, it can prevent other members from starting if the "offline" member potentially holds a more recent copy of the data dictionary. In this case, members will display a ConflictingPersistentDataException when attempting to start. Create a Disk Store You create a named disk store in the data dictionary using the CREATE DISKSTORE DDL statement. You then assign the disk store to an individual table by specifying the disk store in the table's CREATE TABLE DDL statement. You can store data from multiple tables and queues in the same named disk store. Persist Table Data to a Disk Store You configure the persistence settings for a partitioned or replicated table when you create the table with the CREATE TABLE DDL statement. SQLFire automatically recovers data from disk for persistent tables when you restart SQLFire members. Procedure 1. Ensure that the data dictionary is persisted in your SQLFire cluster. SQLFire persists the data dictionary by default for all data stores, but you can explicitly enable or disable data dictionary persistence using the persist-dd boot property. Note: All SQLFire data stores in the same cluster must use a consistent persist-dd value. Accessors cannot persist data, and you cannot set persist-dd to true for an accessor. 92 vFabric SQLFire User's Guide Using Disk Stores to Persist Data 2. Create the disk store that you want to use for persisting the table's data, or use the default disk store. See Creating a Disk Store or Using the Default on page 92. 3. Specify table persistence and the named disk store in the CREATE TABLE statement. For example: CREATE TABLE Orders(OrderId INT NOT NULL,ItemId INT ) persistent 'OrdersDiskStore' asynchronous This example uses asynchronous writes to persist table data to the "OrdersDiskStore." Note: Persistent tables must be associated with a disk store. If you do not specify a named disk store in the CREATE TABLE statement, SQLFire persists the table to the default disk store. For example, the following statement persists the new table to the default disk store: CREATE TABLE Orders(OrderId INT NOT NULL,ItemId INT ) persistent asynchronous Note: When you specify asynchronous persistence, asynchronous writes to the disk store use certain disk store attributes. See Disk Store Persistence Attributes on page 87. Related Topics CREATE DISKSTORE on page 494 CREATE TABLE on page 505 Evicting table data from memoryUse eviction to remove table data from memory, or to persist the overflow data in a disk store. Optimizing Availability and Performance Be aware of what you can do to optimize availability and performance of disk stores. Consider these guidelines: • When you start your system, start all the members that have persistent tables in parallel. Create and use startup scripts for consistency and completeness. • Shut down your system using the sqlf shut-down-all command. This is an ordered shutdown that shuts down all data stores and accessors, but leaves locators and JMX agents running. When shutting down an entire system, a locator should be the last member to shut down (after all data stores have successfully stopped). • Decide on a file compaction policy and, if needed, develop procedures to monitor your files and execute regular compaction. • Decide on a backup strategy for your disk stores and follow it. You can back up by copying the files while the system is offline, or you can back up an online system using the sqlf backup command. • If you drop or alter any persistent table while your disk store is offline, consider synchronizing the tables in your disk stores. Starting System with Disk Stores When you shut down a member that persists data, the data remains in the disk store files, available to be reloaded when the member starts up again. Keep in mind that peer clients are dependent on locators or data store members to persist data, as they cannot persist data on their own. The following sections explain what happens during startup and shutdown: • Shutdown: Most Recent Data from the Last Run on page 93 • Startup Process on page 94 • Example Startup Scenarios on page 95 93 Managing Your Data in vFabric SQLFire Shutdown: Most Recent Data from the Last Run If more than one member has the same persistent table or queue, the last member to exit leaves the most up-to-date data on disk. SQLFire stores information on member exit order in the disk stores, so it can start your members with the most recent data set: • For a persistent replicated table, the last member to exit leaves the most recent data on disk. • For a partitioned table, where the data is split into buckets, the last member to exist that hosts a particular bucket leaves the most recent data on disk for that bucket. Note: Peer clients rely on data stores for persistence. See Peer Client Considerations for Persistent Data on page 92. Startup Process When you start a member with disk stores, the stores are loaded back into memory to initialize the member’s table data. Note: Peer clients rely on data stores for persistence. See Peer Client Considerations for Persistent Data on page 92. If the member does not hold all of the most recent data in the system: 1. The member does not immediately join the server group, but waits for the member with the most recent data. If your log level is info or below, the system provides messaging about the wait. Here, the disk store for hostA has the most recent data and the hostB member is waiting for it. [info 2010/04/09 10:48:26.039 PDT CacheRunner
tid=0x1] Region /persistent_PR initialized with data from /10.80.10.64:/export/straw3/users/jpearson/GemFireTesting/hostB/ backupDirectory created at timestamp 1270834766425 version 0 is waiting for the data previously hosted at [/10.80.10.64:/export/straw3/users/jpearson/GemFireTesting/hostA/ backupDirectory created at timestamp 1270834763353 version 0] to be available During normal startup you can expect to see some waiting messages. 2. When the most recent data is available, the system updates the local tables as needed, logs a message like this, and continues with startup. [info 2010/04/09 10:52:13.010 PDT CacheRunner
tid=0x1] Done waiting for the remote data to be available. Each member’s persistent tables load and go online as quickly as possible, not waiting unnecessarily for other members to complete. For performance reasons, several actions are taken asynchronously: • If both primary and secondary buckets are persisted, data is made available when the primary buckets are loaded without waiting for the secondary buckets to load. The secondary buckets will load asynchronously. • Entry keys first get loaded from the key file if this file is available (see information about the krf file in Disk Store File Names and Extensions on page 87). Once all keys are loaded, SQLFire loads the entry values asynchronously. If a value is requested before it is loaded, the value will immediately be fetched from the disk store. 94 vFabric SQLFire User's Guide Using Disk Stores to Persist Data Example Startup Scenarios • Stop order for a replicated, persistent table: 1. Member A (MA) exits first, leaving persisted data on disk for TableP. 2. Member B (MB) continues to run DML operations on TableP, which update its disk store and leaves the disk store for MA in a stale condition. 3. MB exits, leaving the most up-to-date data on disk for Table P. • Restart order Scenario 1: 1. MB is started first. SQLFire recognizes MB as having the most recent disk data for TableP and initializes it from disk. 2. MA is started, recovers its data from disk, and updates it as needed from the data in MB. • Restart order Scenario 2: 1. MA is started first. SQLFire recognizes that MA does not have the most recent disk store data and waits for MB to start before creating TableP in MA. 2. MB is started. SQLFire recognizes MB as having the most recent disk data for TableP and initializes it from disk. 3. MA recovers its TableP data from disk and updates it as needed from the data in MB. Start a System with Disk Stores When you start a SQLFire cluster with disk stores, it is recommended that you start all members with persisted data at the same time. Procedure 1. Start members with persisted data at the same time. When members with persistent data boot, they determine which have the most recent table data, and they initialize their caches using that data. If you do not start persistent data stores in parallel, some members may hang while waiting for other members to start. The following example bash script starts members in parallel. The script waits for the startup to finish and exits with an error status if one of the jobs fails. #!/bin/bash # Start all local SQLFire members to waiting state, regardless of which member holds the most recent # disk store files: ssh servera "sqlf locator start -dir=/locator1 -sync=false" ssh serverb "sqlf server start -client-port=1528 -locators=localhost[10334] -dir=/server1 -sync=false" ssh serverc "sqlf server start -client-port=1529 -locators=localhost[10334] -dir=/server2 -sync=false" # Wait until all members have finished synchronizing and starting: ssh servera "sqlf locator wait -dir=/locator1" ssh serverb "sqlf server wait -dir=/server1" ssh serverc "sqlf server wait -dir=/server2" # Continue any additional tasks that require access to the SQLFire members... [...] 95 Managing Your Data in vFabric SQLFire 2. Respond to any member startup hangs. If a disk store with the most recent table data does not come online, other members wait indefinitely rather than come online with stale data. Check for missing disk stores with the sqlf list-missing-disk-stores command. See Handling Missing Disk Stores on page 102. a. If no disk stores are missing, your peer initialization may be slow for some other reason. Check to see if other members are hanging or fail to start. b. If disk stores are missing that you think should be there: a. Make sure you have started the member. Check the logs for any failure messages. b. Make sure your disk store files are accessible. If you have moved your member or disk store files, you must update your disk store configuration to match. c. If disk stores are missing that you know are lost, because you have deleted them or their files are otherwise unavailable, revoke them so the startup can continue. See Handling Missing Disk Stores on page 102. Disk Store Management The sqlf command-line tool has several options for examining and managing your disk stores. The sqlf tool, along with the CREATE DISKSTORE statement, are your management tools for online and offline disk stores. Note: Each of these commands operates either on the online disk stores or offline disk stores, but not both. sqlf Command Online or Offline Command See . . . validate-disk-store Off Validate a Disk Store on page 97 compact-all-disk-stores On Compacting Disk Store Log Files on page 97 compact-disk-store Off Compacting Disk Store Log Files on page 97 backup On Backing Up and Restoring Online Disk Stores on page 100 list-missing-disk-stores On Handling Missing Disk Stores on page 102 revoke-missing-disk-store On Handling Missing Disk Stores on page 102 For the complete command syntax of any sqlf command, run sqlf --help at the command line. Online sqlf Disk Store Operations For online operations, sqlf connects to a distributed system and sends the operation requests to the members that have disk stores. These commands do not run on offline disk stores. You must provide the command with a distributed system properties in a sqlfire.properties file, or specify the multicast port or locator properties to connect to the cluster (for example, -mcast-port= port_number). Offline sqlf Disk Store Operations For offline operations, sqlf runs the command against the specified disk store and its specified directories. You must specify all directories for the disk store. Offline operations will not run on online disk stores. The tool locks the disk store while it is running, so the member cannot start in the middle of an operation. 96 vFabric SQLFire User's Guide Using Disk Stores to Persist Data If you try to run an offline command for an online disk store, you get a message like this: ERROR: Operation "validate-disk-store" failed because: disk-store=ds1: com.gemstone.gemfire.cache.DiskAccessException: For DiskStore: ds1: Could not lock "hostA/ds1dir1/DRLK_IFds1.lk". Other JVMs might have created diskstore with same name using the same directory., caused by java.io.IOException: The file "hostA/ds1dir1/DRLK_IFds1.lk" is being used by another process. Validate a Disk Store The sqlf validate-disk-store command verifies the health of your offline disk store. It gives you information about the tables in it, the total rows, and the number of records that would be removed if you compacted the store. When to use this command: • Before compacting an offline disk store to help decide whether it’s worth doing. • Before restoring a disk store. • Any time you want to be sure the disk store is in good shape. Example sqlf validate-disk-store ds1 hostB/bupDirectory /partitioned_table entryCount=6 bucketCount=10 Disk store contains 1 compactable records. Total number of table entries in this disk store is: 6 Compacting Disk Store Log Files You can configure automatic compaction for an operation log based on percentage of garbage content. You can also request compaction manually for online and offline disk stores. The following topics deal with compaction: • How Compaction Works on page 97 • Online Compaction Diagram on page 98 • Run Online Compaction on page 98 • Run Offline Compaction on page 99 • Performance Benefits of Manual Compaction on page 99 • Directory Size Limits on page 99 • Example Compaction Run on page 99 How Compaction Works When a DML operation is added to a disk store, any preexisting operation record for the same record becomes obsolete, and SQLFire marks it as garbage. For example, when you update a record, the update operation is added to the store. If you delete the record later, the delete operation is added and the update operation becomes garbage. SQLFire does not remove garbage records as it goes, but it tracks the percentage of garbage in each operation log, and provides mechanisms for removing garbage to compact your log files. SQLFire compacts an old operation log by copying all non-garbage records into the current log and discarding the old files. As with logging, oplogs are rolled as needed during compaction to stay within the MAXLOGSIZE setting. You can configure the system to automatically compact any closed operation log when its garbage content reaches a certain percentage. You can also manually request compaction for online and offline disk stores. For 97 Managing Your Data in vFabric SQLFire the online disk store, the current operation log is not available for compaction, no matter how much garbage it contains. Online Compaction Diagram Offline compaction runs essentially in the same way, but without the incoming DML operations. Also, because there is no current open log, the compaction creates a new one to get started. Run Online Compaction Old log files become eligible for online compaction when their garbage content surpasses a configured percentage of the total file. A record is garbage when its operation is superseded by a more recent operation for the same record. During compaction, the non-garbage records are added to the current log along with new DML operations. Online compaction does not block current system operations. • Run automatic compaction. When AUTOCOMPACT is true, SQLFire automatically compacts each oplog when its garbage content surpasses the COMPACTIONTHRESHOLD. Automatic compaction takes cycles from your other operations, so you may want to disable it and only do manual compaction, to control the timing. • Run manual compaction. To run manual compaction: • Set the disk store attribute ALLOWFORCECOMPACTION to true. This causes SQLFire to maintain extra data about the files so that it can compact on demand. This is disabled by default to save space. You can run manual online compaction at any time while the system is running. Oplogs eligible for compaction based on the COMPACTIONTHRESHOLD are compacted into the current oplog. • Run manual compaction as needed. You can compact all online disk stores in a distributed system from the command-line. For example: sqlf compact-all-disk-stores Note: This sqlf command requires a local sqlfire.properties file that contains properties to locate the distributed system. Or, specify the multicast port or locator properties to connect to the cluster (for example, -mcast-port= port_number). 98 vFabric SQLFire User's Guide Using Disk Stores to Persist Data Run Offline Compaction Offline compaction is a manual process. All log files are compacted as much as possible, regardless of how much garbage they hold. Offline compaction creates new log files for the compacted log records. Use this syntax to compact individual offline disk stores: sqlf compact-disk-store myDiskStoreName /firstDir /secondDir -maxOplogSize=maxMegabytesForOplog You must provide all of the directories in the disk store. If no oplog max size is specified, SQLFire uses the system default. Offline compaction can take a lot of memory. If you get a java.lang.OutOfMemory error while running this, you made need to increase your heap size. See the sqlf command help for instructions on how to do this. Performance Benefits of Manual Compaction You can improve performance during busy times if you disable automatic compaction and run your own manual compaction during lighter system load or during downtimes. You could run the API call after your application performs a large set of data operations. You could run sqlf compact-all-disk-stores every night when system use is very low. To follow a strategy like this, you need to set aside enough disk space to accommodate all non-compacted disk data. You might need to increase system monitoring to make sure you do not overrun your disk space. You may be able to run only offline compaction. If so, you can set ALLOWFORCECOMPACTION to false and avoid storing the information required for manual online compaction. Directory Size Limits If you reach the disk directory size limits during compaction: • For automatic compaction, the system logs a warning, but does not stop. • For manual compaction, the operation stops and returns a DiskAccessException to the calling process, reporting that the system has run out of disk space. Example Compaction Run In this example offline compaction run listing, the disk store compaction had nothing to do in the *_3.* files, so they were left alone. The *_4.* files had garbage records, so the oplog from them was compacted into the new *_5.* files. bash-2.05$ ls -ltra backupDirectory total 28 -rw-rw-r-1 jpearson users 3 Apr -rw-rw-r-1 jpearson users 25 Apr drwxrwxr-x 3 jpearson users 1024 Apr -rw-rw-r-1 jpearson users 7085 Apr -rw-rw-r-1 jpearson users 18 Apr -rw-rw-r-1 jpearson users 1070 Apr drwxrwxr-x 2 jpearson users 512 Apr 7 7 7 7 7 7 7 14:56 14:56 15:02 15:06 15:07 15:07 15:07 BACKUPds1_3.drf BACKUPds1_3.crf .. BACKUPds1.if BACKUPds1_4.drf BACKUPds1_4.crf . bash-2.05$ sqlf validate-disk-store ds1 backupDirectory /root: entryCount=6 /partitioned_region entryCount=1 bucketCount=10 Disk store contains 12 compactable records. Total number of region entries in this disk store is: 7 bash-2.05$ sqlf compact-disk-store ds1 backupDirectory Offline compaction removed 12 records. Total number of region entries in this disk store is: 7 99 Managing Your Data in vFabric SQLFire bash-2.05$ ls -ltra backupDirectory total 16 -rw-rw-r-1 jpearson users 3 Apr -rw-rw-r-1 jpearson users 25 Apr drwxrwxr-x 3 jpearson users 1024 Apr -rw-rw-r-1 jpearson users 0 Apr -rw-rw-r-1 jpearson users 638 Apr -rw-rw-r-1 jpearson users 2788 Apr drwxrwxr-x 2 jpearson users 512 Apr bash-2.05$ 7 7 7 7 7 7 7 14:56 14:56 15:02 15:08 15:08 15:08 15:09 BACKUPds1_3.drf BACKUPds1_3.crf .. BACKUPds1_5.drf BACKUPds1_5.crf BACKUPds1.if . Backing Up and Restoring Online Disk Stores When you invoke the sqlf backup command, SQLFire backs up disk stores for all members that are running in the distributed system at that time. Each member with persistent data creates a backup of its own configuration and disk stores. • Backup Guidelines and Prerequisites on page 100 • Back Up an Online Disk Store on page 100 • What the Online Backup Saves on page 101 • Restore an Online Backup on page 101 Backup Guidelines and Prerequisites • Run the backup during a period of low activity in your system. The backup does not block any activities in the distributed system, but it does use file system resources on all hosts in your distributed system and can affect performance. • Optionally, compact your disk store before running the backup. See Compacting Disk Store Log Files on page 97. • Only use the sqlf backup command to create backup files from a running distributed system. Do not try to create backup files from a running system using file copy commands. You will get incomplete and unusable copies. • Back up to a directory that all members can access. Make sure the directory exists and has the proper permissions for your members to write to it and create subdirectories. • Make sure there is a sqlfire.properties file for the distributed system in the directory where you will run the sqlf command, or specify the multicast port or locator properties to connect to the cluster (for example, -mcast-port= port_number). The command will back up all disk stores in the specified distributed system. • The directory you specify for backup can be used multiple times. Each backup first creates a top level directory for the backup, under the directory you specify, identified to the minute. You can specify a directory by one of two methods; the command in the procedure below uses the first method. • Use a single physical location, such as a network file server. Example: /export/fileServerDirectory/sqlfBackupLocation • Use a directory that is local to all host machines in the system. Example: ./sqlfBackupLocation Back Up an Online Disk Store 1. Run the backup command, providing your backup directory location. Example: sqlf backup /export/fileServerDirectory/gemfireBackupLocation -locators=warsaw.vmware.com[26340] 100 vFabric SQLFire User's Guide Using Disk Stores to Persist Data 2. Read the message that reports on the success of the operation. If the operation is successful, you see a message like this: Connecting to distributed system: locators=warsaw.vmware.com[26340] The following disk stores were backed up: DiskStore at hosta.vmware.com /home/dsmith/dir1 DiskStore at hostb.vmware.com /home/dsmith/dir2 Backup successful. If the operation does not succeed at backing up all known members, you see a message like this: Connecting to distributed system: locators=warsaw.vmware.com[26357] The following disk stores were backed up: DiskStore at hosta.vmware.com /home/dsmith/dir1 DiskStore at hostb.vmware.com /home/dsmith/dir2 The backup may be incomplete. The following disk stores are not online: DiskStore at hostc.vmware.com /home/dsmith/dir3 A member that fails to complete its backup is noted in this ending status message and leaves the file INCOMPLETE_BACKUP in its highest level backup directory. Offline members leave nothing, so you only have this message from the backup operation itself. Although offline members cannot back up their disk stores, a complete backup can be obtained if at least one copy of the data is available in a running member. What the Online Backup Saves For each member with persistent data, the backup includes: • Disk store files for all stores containing persistent tables. • Configuration files from the member startup (sqlfire.properties). These configuration files are not automatically restored, to avoid interfering with any more recent configurations. In particular, if these are extracted from a master jar file, copying the separate files into your working area could override the files in the jar. • A restore script, written for the member’s operating system, that copies the files back to their original locations. For example, in Windows, the file is restore.bat and in Linux, it is restore.sh. Restore an Online Backup The restore script included in the online backup copies files back to their original locations. You can do this manually if you wish. Prerequisites Your members are offline and the system is down. Procedure 1. Read the restore scripts to see where they will place the files and make sure the destination locations are ready. The restore scripts refuse to copy over files with the same names. 2. Run each restore script on the host where the backup originated. In Windows, the file is restore.bat and in Linux, it is restore.sh. The restore copies the files back to their original location. Backing Up and Restoring Offline Disk Stores With the system offline, you copy and restore your files using your file system commands. • Offline File Backup and Restore on page 101 • Offline Members: Manual Catch-Up to an Online Backup on page 102 101 Managing Your Data in vFabric SQLFire Offline File Backup and Restore To back up your offline system: 1. Validate, and consider compacting your disk stores before backing them up. See Compacting Disk Store Log Files on page 97. 2. Copy all disk store files, and any other files you want to save, to your backup locations. To restore a backup of an offline system: 1. Make sure the system is either down or not using the directories you will use for the restored files. 2. Make sure your members are configured to use the directories where you put the files. 3. Reverse your backup file copy procedure, copying all the backed up files into the directories you want to use. 4. Start the system members. Offline Members: Manual Catch-Up to an Online Backup If you must have a member offline during an online backup, you can manually back up its disk stores. Do one of the following: • Keep the member’s backup and restore separated, doing offline manual backup and offline manual restore, if needed. • Bring this member’s files into the online backup framework manually and create a restore script by hand, from a copy of another member’s script: 1. 2. 3. 4. 5. Duplicate the directory structure of a backed up member for this member. Rename directories as needed to reflect this member’s particular backup, including disk store names. Clear out all files but the restore script. Copy in this member’s files. Modify the restore script to work for this member. Handling Missing Disk Stores Use the sqlf list-missing-disk-stores command to find disk stores with the latest persisted data. Use sqlf revoke-missing-disk-stores to stop waiting for the data when you cannot bring it online. • Why Disk Stores Go Missing on page 102 • List Missing Disk Stores on page 103 • Revoke Missing Disk Stores on page 103 Why Disk Stores Go Missing Disk stores usually go missing because their member fails to start. The member can fail to start for a number of reasons, including: • Disk store file corruption. You can check on this by validating the disk store. • Incorrect distributed system configuration for the member • Network partitioning • Drive failure Note: The disk store directories listed for missing disk stores may not be the directories you have currently configured for the member. The list is retrieved from the other running members—the ones who are reporting the missing member. They have information from the last time the missing disk store was online. If you move your files and change the member’s configuration, these directory locations will be stale. 102 vFabric SQLFire User's Guide Using Disk Stores to Persist Data List Missing Disk Stores The sqlf list-missing-disk-stores command lists all disk stores with most recent data that are being waited on by other members. For replicated tables, this command only lists missing members that are preventing other members from starting up. For partitioned tables, this command also lists any offline data stores, even when other data stores for the table are online, because their offline status may be causing PartitionOfflineExceptions in cache operations or preventing the system from satisfying redundancy. Example: sqlf list-missing-disk-stores Connecting to distributed system: mcast=/239.192.81.2:12348 DiskStore at straw.gemstone.com /export/straw3/users/jpearson/testGemFire/hostB/DS1 Note: Make sure this sqlf call can find a sqlfire.properties file to locate the distributed system. Or, specify the multicast port or locator properties to connect to the cluster (for example, -mcast-port= port_number). Revoke Missing Disk Stores This section applies to disk stores for which both of the following are true: • Disk stores that have the most recent copy of data for one or more tables or table buckets. • Disk stores that are unrecoverable, such as when you have deleted them, or their files are corrupted or on a disk that has had a catastrophic failure. When you cannot bring the latest persisted copy online, use the revoke command to tell the other members to stop waiting for it. Once the store is revoked, the system finds the remaining most recent copy of data and uses that. Note: Once revoked, a disk store cannot be reintroduced into the system. Use the sqlf list-missing-disk-stores command to identify the disk store you need to revoke. The revoke command takes the host and directory in input, as listed by that command. Example: sqlf list-missing-disk-stores Connecting to distributed system: mcast=/239.192.81.2:12348 DiskStore at straw.gemstone.com /export/straw3/users/jpearson/testGemFire/hostB/DS1 sqlf revoke-missing-disk-store straw.gemstone.com /export/straw3/users/jpearson/testGemFire/hostB/DS1 Connecting to distributed system: mcast=/239.192.81.2:12348 revocation was successful ... Note: Make sure this sqlf call can find a sqlfire.properties file to locate the distributed system. Or, specify the multicast port or locator properties to connect to the cluster (for example, -mcast-port= port_number). 103 Chapter 15 Exporting and Importing Data with vFabric SQLFire You can use either sqlf commands or Apache DdlUtils to import data into SQLFire. SQLFire installs and uses DdlUtils for sqlf import and export functionality. Using SQLF Commands to Export and Import Data The sqlf utility provides several commands that use the DdlUtils 1.1 API to export and import database schemas and table data. You can use these sqlf commands with SQLFire and other JDBC datasources. Note: As a best practice, use the SYS.CREATE_ALL_BUCKETS procedure to pre-allocate partitioned table buckets before you import data into a partitioned table. This helps to ensure that partitioned table data is evenly distributed throughout the distributed system, even if you import table data using concurrent processes. These sqlf commands are used to write existing database information to files: • sqlf write-schema-to-sql—Writes a database schema to a file as SQL DDL statements. • sqlf write-schema-to-xml—Writes a database schema to a schema XML file. • sqlf write-data-to-xml—Writes table data to a data XML file. • sqlf write-data-dtd-to-file—Writes a Document Type Definition (DTD) that describes the layout of a data XML file (created using sqlf write-data-to-xml). These sqlf commands are used to import database information from files: • sqlf write-schema-to-db—Creates a database schema from a schema XML file. • sqlf write-data-to-db—Inserts table data into a schema using one or more data XML files and schema XML files. When you migrate a third-party database schema to SQLFire, use sqlf write-schema-to-sql and then modify the SQL statements to include SQLFire-specific features such as table partitioning and replication. Then use an interactive sqlf session to execute the script in SQLFire. See run on page 470. When you migrate a schema from one SQLFire system to another, use sqlf write-schema-to-xml or use sqlf write-schema-to-sql with the -dump-from-db option to include SQLFire-specific extensions in the DDL commands. Note: Databases such as Oracle 11g contain system tables with data types that are incompatible with the DdlUtils 1.1 API. To export schemas or data from these databases, you must use the -schema-pattern option with the sqlf command to exclude schemas that contain incompatible data types. See sqlf write-schema-to-xml. 105 Managing Your Data in vFabric SQLFire The sections that follow describe how to use the above sqlf commands to migrate a third-party database to SQLFire. Export, Alter, and Import a Database Schema Using SQLF Use sqlf commands to export the schema and data from a third-party database, and then import the schema and data to vFabric SQLFire. Procedure 1. To use the sqlf export commands with a third-party database, you require a JDBC driver and connection URL for the database. Use a Java client application such as SQuirreL SQL to verify that you can connect to the database. This procedure uses MySQL as an example datasource. The components necessary to establish a JDBC connection the example server are: • Driver JAR file: mysql-connector-java-5.1.18-bin.jar • Driver class: com.mysql.jdbc.Driver • Connection URL: jdbc:mysql://localhost:3306/sqlfdb?user=username&password=password To ensure that sqlf can access the JDBC driver class, add the JAR location to your CLASSPATH. For example, open a new command prompt and enter: export CLASSPATH=$CLASSPATH:/path/mysql-connector-java-5.1.18-bin.jar 2. Add the SQLFire /bin directory to your path if you have not already done so. For example: export PATH=$PATH:~/vFabric_SQLFire_11_bNNNNN/bin 3. Use sqlf to export the schema of the third-party data source to a schema SQL file in a format that is compatible with SQLFire. For example: sqlf write-schema-to-sql -file=mysql-schema.sql -to-database-type=sqlfire -driver-class=com.mysql.jdbc.Driver -url=jdbc:mysql://localhost:3306/sqlfdb?user=username&password=password Note: Databases such as Oracle 11g contain system tables with data types that are incompatible with the DdlUtils 1.1 API. To export schemas or data from these databases, you must use the -schema-pattern option with the sqlf command to exclude schemas that contain incompatible data types. See sqlf write-schema-to-xml. 4. Edit the CREATE TABLE statements in the resulting schema SQL file to use SQLFire-specific clauses. For example use syntax to specify colocation for partitioning, persist tables, associate tables with gateways, and so forth. 5. After editing the SQL script file, use an interactive sqlf session to execute the script in SQLFire: sqlf connect client 'localhost:1527'; run 'mysql-schema.sql'; 6. Pre-allocate buckets for partitioned table data before you import import the data, and exit sqlf: call sys.create_all_buckets; exit; 7. To import the data from the third-party datasource, first use these sqlf commands to export both the data and schema to XML files: sqlf write-schema-to-xml -file=mysql-schema.xml -driver-class=com.mysql.jdbc.Driver 106 vFabric SQLFire User's Guide Exporting and Importing Data with vFabric SQLFire -url=jdbc:mysql://localhost:3306/sqlfdb?user=username&password=password sqlf write-data-to-xml -file=mysql-data.xml -driver-class=com.mysql.jdbc.Driver -url=jdbc:mysql://localhost:3306/sqlfdb?user=username&password=password 8. Use the sqlf write-data-to-db command and specify both the data XML file and the schema XML file to import the data to SQLFire: sqlf write-data-to-db -files=mysql-data.xml -schema-files=mysql-schema.xml -client-bind-address=localhost -client-port=1527 9. If necessary, manually add triggers, views, and Java stored procedures in the SQLFire database. Using Apache DdlUtils to Import Data The SQLFire installation includes Apache DdlUtils 1.1, and you can use DdlUtils in combination with Apache Ant to import data into SQLFire. The information in these sections is intended for customers who are familiar with DdlUtils and want to use DdlUtils in place of the available sqlf commands. Overview of DdlUtils DdlUtils is a small, easy-to-use component for working with Database Definition (DDL) files. DdlUtils is an Apache project. Use it to: • Generate DDL scripts from an existing database by using Ant tasks or a Java API. • Export and import data to/from XML from an supported database to another supported database (including SQLFire). • Take XML files that contain the definition of a database schema, for example, tables and columns. These files can be fed into DdlUtils through its Ant task or programmatically in order to create the corresponding database or alter it so that it corresponds to the DDL. Likewise, DdlUtils can generate a DDL file for an existing database. Note: The instructions in this section use a version of DdlUtils that has been modified to support SQLFire and its SQL dialect. This version of DdlUtils is installed with SQLFire, and is available in the vFabric_SQLFire_11_bNNNNN/lib/ddlutils directory. Ensure that you use the installed version of DdlUtils, rather than the standard Apache version, when performing the instructions. A common usage pattern with SQLFire is as a database cache in front of a relational data store. DdlUtils provides a way to export the schema definition from a relational database as a SQL script so the developer can tailor it for partitioning and replication and then import the schema into SQLFire. DdlUtils can optionally be used to export from an external database and import the same into SQLFire. Note: If you attempt to export and import data that includes auto-generated primary key columns, the data row import fails. SQLFire adds distributed system data into generated keys, and this precludes referencing those generated keys by subsequent imported data rows. Export, Alter, and Import a Database Schema Using DdlUtils Use DdlUtils to export, modify, and import data. Procedure 1. Download and install Apache Ant if it is not already available on your system. 2. Ensure that your CLASSPATH includes the JAR file that contains the third-party database's JDBC driver. 107 Managing Your Data in vFabric SQLFire 3. Read the available DdlUtils documentation to understand the various Ant tasks. Documentation is installed in the ddlutils/DdlUtils-1.0-doc.zip file and is also available at the DdlUtils project site. This step is not required if you only want to export DDL from a schema and then apply it to SQLFire. 4. Make sure that you can connect to the external database and to SQLFire servers. You will need to supply the connection URL and properties for both databases when using DdlUtils. 5. Edit the build.xml file in the ddlutils/example directory to specify the JDBC connection information for both SQLFire and the database from which you are importing data. The example build file contains sample entries for SQLFire and MySQL. You will need to change each occurrence of the JDBC URLs. The build.xml contents are shown in the Example build.xml File on page 108. 6. By default, the usedelimitedsqlidentifiers property is set to false, which means that tables, columns, and other object names are simple references with no need to place the names in quotation marks. However, if your schema contains table or column names with embedded spaces, change this property to "true" and use single quotation marks around the table and column names each time you reference them. 7. Databases such as Oracle 11g contain system tables with data types that are incompatible with the DdlUtils 1.1 API. To export schemas or data from these databases, you must use the schemapattern property to exclude schemas that contain incompatible data types. 8. In the ddlutils/example directory, run the following command to run the three Ant tasks that generate a SQL DDL script that is compatible with SQLFire syntax: ant writeDDLToXML createDBFromXML writeDDLToSQL 9. Edit the CREATE TABLE statements in the resulting script to use SQLFire-specific clauses. For example use syntax to use colocation for partitioning, persist tables, associate tables with gateways, and so forth. 10. Use the sqlf utility to run the modified script in SQLFire. For example: sqlf connect client 'localhost:1527'; run 'db-schema1.sql'; exit; 11. To import data from the database, use the ImportDataToDB target in the example build.xml file. 12. If necessary, manually add triggers, views, and Java stored procedures in the SQLFire database. Example build.xml File View a sample build file for using DdlUtils with SQLFire. --> 109 Managing Your Data in vFabric SQLFire Exporting and Importing Data from Text Files SQLFire provides several procedures to help you import and export delimited data in text files. You can use these procedures to transfer data between various programs and SQLFire. For example, you can use the procedures to import data as comma-separated values (a CSV file). Note: As a best practice, use the SYS.CREATE_ALL_BUCKETS procedure to pre-allocate partitioned table buckets before you import data into a partitioned table. This helps to ensure that partitioned table data is evenly distributed throughout the distributed system, even if you import table data using concurrent processes. These procedures are used to export and import data using delimited text files: • SYSCS_UTIL.EXPORT_QUERY—Writes the results of a SQLFire query to a text file using delimiters that you specify. • SYSCS_UTIL.EXPORT_TABLE—Writes the data from a SQLFire table to a text file using delimiters that you specify. 110 vFabric SQLFire User's Guide Exporting and Importing Data with vFabric SQLFire • SYSCS_UTIL.IMPORT_TABLE_EX—Writes data from a delimited text file to all columns of a SQLFire table. • SYSCS_UTIL.IMPORT_DATA_EX—Writes data from a delimited text file to a subset of columns in a SQLFire table. See Standard Built-in Procedures on page 609 for examples that use these procedures. 111 Chapter 16 Using Table Functions to Import Data as a SQLFire Tables A SQLFire table function lets you efficiently import foreign data into SQLFire tables. Table functions let you join SQLFire tables with any of the following data sources: • XML-formatted reports and logs • Queries that run in foreign databases • Streaming data from sensors • RSS feeds The data imported by a table function acts like a SQLFire replicated table that has no indexes. All data is fetched on every SQLFire member where a query against the table is executed. Outer joins that involve a partitioned table and a table function have limitations similar to joins with replicated tables (duplicate values are returned from the replicated table or table function). See CREATE FUNCTION on page 496 for the complete syntax needed to declare SQLFire table functions. The following topics provide information on how to write Java methods that wrap foreign data sources inside JDBC ResultSets. Overview of SQLFire Table Functions A SQLFire table function is a Java method that returns a JDBC ResultSet. Most of the ResultSet methods can be written as stubs that simply raise exceptions. However, a SQLFire table function must implement the following ResultSet methods: • next() • close() • wasNull() • getXXX() - When invoking a SQLFire table function at runtime, SQLFire calls a getXXX() method on each referenced column. The particular getXXX() method is based on the column's data type as declared in the CREATE FUNCTION statement. Preferred getXXX() methods for SQLFire Table Functions on page 114 explains how SQLFire selects an appropriate getXXX() method. However, nothing prevents application code from calling other getXXX() methods on the ResultSet. The returned ResultSet needs to implement the getXXX() methods which SQLFire will call as well as all getXXX() methods which the application will call. 113 Managing Your Data in vFabric SQLFire A SQLFire table function is materialized by a public static method that returns a ResultSet: public static ResultSet read() {...} The public static method is then bound to a SQLFire function name: CREATE FUNCTION externalEmployees () RETURNS TABLE ( employeeId INT, lastName VARCHAR( 50 ), firstName VARCHAR( 50 ), birthday DATE ) LANGUAGE JAVA PARAMETER STYLE DERBY_JDBC_RESULT_SET READS SQL DATA EXTERNAL NAME 'com.acme.hrSchema.EmployeeTable.read' To invoke a table function, wrap it in a TABLE constructor in the FROM list of a query. Note that the table alias (in this example "s") is a required part of the syntax: INSERT INTO employees SELECT s.* FROM TABLE (externalEmployees() ) s; Preferred getXXX() methods for SQLFire Table Functions While scanning a table function, SQLFire calls a preferred getXXX() method for each column, based on the column's data type. The following table lists the preferred getXXX() method for each SQLFire data type. Table 3: getXXX() Methods Called for Declared SQL Types 114 Column Type Declared by CREATE FUNCTION getXXX() Method Called by SQLFire for JDBC 3.0 and 4.0 BIGINT getLong() BLOB getBlob() CHAR getString() CHAR FOR BIT DATA getBytes() CLOB getClob() DATE getDate() DECIMAL getBigDecimal() DOUBLE getDouble() DOUBLE PRECISION getDouble() FLOAT getDouble() INTEGER getInt() LONG VARCHAR getString() LONG VARCHAR FOR BIT DATA getBytes() vFabric SQLFire User's Guide Using Table Functions to Import Data as a SQLFire Tables Column Type Declared by CREATE FUNCTION getXXX() Method Called by SQLFire for JDBC 3.0 and 4.0 NUMERIC getBigDecimal() REAL getFloat() SMALLINT getShort() TIME getTime() TIMESTAMP getTimestamp() VARCHAR getString() VARCHAR FOR BIT DATA getBytes() XML Not supported Example Table Function The following simple table function selects rows from a foreign database. package com.acme.hrSchema; import java.sql.*; /** * Sample Table Function for reading the employee table in an * external database. */ public class EmployeeTable { public static ResultSet read() throws SQLException { Connection conn = getConnection(); PreparedStatement ps = conn.prepareStatement( "select * from hrSchema.EmployeeTable" ); return ps.executeQuery(); } protected static Connection getConnection() throws SQLException { String EXTERNAL_DRIVER = "com.mysql.jdbc.Driver"; try { Class.forName( EXTERNAL_DRIVER ); } catch (ClassNotFoundException e) { throw new SQLException( "Could not find class " + EXTERNAL_DRIVER ); } Connection conn = DriverManager.getConnection ( "jdbc:mysql://localhost/hr?user=root&password=mysql-passwd" ); return conn; } } 115 Part 5 Developing Applications with SQLFire Developing Applications with vFabric SQLFire explains the main concepts of programming Java and ADO.NET applications with SQLFire APIs and the SQLFire implementation of SQL. It describes how to embed a SQLFire instance in a Java application and how to connect as a client. This guide also describes transactional and non-transactional behavior, and explains how to create data-aware stored procedures. Topics: • • • • • • • • • • • • • • Starting SQLFire Servers with the FabricServer Interface Developing Java Clients and Peers Configuring SQLFire as a JDBC Datasource Using SQLFire with Hibernate Storing and Loading JAR Files in SQLFire Developing ADO.NET Client Applications Using SQLFire.NET Designer Understanding the Data Consistency Model Using Distributed Transactions in Your Applications Using Data-Aware Stored Procedures Using the Procedure Provider API Using the Custom Result Processor API Programming User-Defined Types Using Result Sets and Cursors 117 Using SQLFire with Hibernate VMware provides a Hibernate dialect file that defines the SQLFire variant of the SQL language. You can use this file along with the SQLFire JDBC driver to configure SQLFire as a database for developing Hibernate projects. VMware provides a Hibernate dialect file that defines the SQLFire variant of the SQL language. You can use this file along with the SQLFire JDBC driver to configure SQLFire as a database for developing Hibernate projects. See vFabric SQLFire Hibernate Dialect at the VMware Community site for information about obtaining and using the SQLFire dialect file with your Hibernate projects. 118 vFabric SQLFire User's Guide Chapter 17 Starting SQLFire Servers with the FabricServer Interface The FabricServer interface provides an easy way to start an embedded SQLFire server process in an existing Java application. You generally use the FabricServer interface when you want to provide thin client connectivity to the embedded SQLFire member. The FabricServer interface enables you to start multiple network services to listen for clients on different address and port combinations. Using the FabricServer interface also enables you to initialize resources in the SQLFire server member before you start network services and make the member available to client connections. Note: Although the FabricServer interface supports starting an embedded locator service, production systems should always use standalone locators. See Start and Stop Locators on page 229. Procedure To start a SQLFire server using the FabricServer interface: 1. Use the FabricServiceManager factory class to obtain the singleton instance of FabricServer. For example: FabricServer server = FabricServiceManager.getFabricServerInstance(); 2. Create a Java Properties object and add all of the boot property definitions that you want to configure when starting the server. For example: Properties bootProps = new Properties(); bootProps.setProperty("mcast-port", "12444"); As an alternative, you can define properties as system properties (pass with the -D option to the JVM), configure them in a properties file, or rely on default property values. Configuration Properties on page 327 provides more information. 3. Use the FabricServer.start() method with start the server using your Properties object: server.start(p); Note: SQLFire supports only a single FabricServer instance in a JVM at any given time. If you invoke start() multiple times using the same Properties, then no action is taken during subsequent calls. If you invoke start() multiple times using different properties, then by default the existing FabricServer instance is first stopped and then restarted with the new properties. You can optionally use the start(Properties bootProperties, boolean ignoreIfStarted) method with a "true" boolean value to reuse a previous instance instead of restarting it. See the FabricServer JavaDoc for more information. 4. To support client connections, start a network service on a unique client and port combination using the startNetworkServer() method. You can specify the host and port number as arguments to the method. You can 119 Developing Applications with SQLFire specify additional network server properties in a Properties object that you pass with the method. For example, to specify only the address and port with no additional properties: server.startNetworkServer("localhost", 1528, null); Note: The SQLFire network server supports the Apache Derby network properties documented in the Derby Server and Administration Guide. 5. Start additional network services as needed to listen on different address and port combinations. Deciding When to Use Embedded Peer-to-Peer on page 220 provides more examples of using the FabricServer interface to embed SQLFire members. Starting a Network Server Clients can connect to a NetworkInterface using the SQLFire JDBC client driver (URL of the form 'jdbc:sqlfire://:'). A network listener can be acquired by invoking the startNetworkServer method on a FabricServer instance. SQLFire uses the Distributed Relational Database Architecture (DRDA) protocol for client-server communication. Network Server Properties Specify network server properties when starting a network server on a SQLFire member. You must specify these properties as system properties: • When using the sqlf utility, specify network server properties at the command line when you boot a SQLFire server. • When using the embedded JDBC driver, specify all network server properties in the first JDBC connection to the SQLFire member. • When using the FabricServer API, you can start the FabricServer instance and NetworkListener independently of one another. For example you can start a FabricServer instance, populate tables with initial or default data, and then start a Network Listener at a later time to enable client connections. Include all Network Server properties in the Properties object when you execute the FabricService.startNetworkServer() method. The FabricServer API promotes properties in the configuration parameter to an equivalent system property if the application does not override them. Network server startup properties use the prefix 'sqlfire.drda.' The following properties are available: sqlfire.drda.host sqlfire.drda.keepAlive sqlfire.drda.logConnections sqlfire.drda.maxThreads sqlfire.drda.minThreads sqlfire.drda.portNumber sqlfire.drda.securityMechanism sqlfire.drda.sslMode sqlfire.drda.streamOutBufferSize sqlfire.drda.timeSlice sqlfire.drda.trace 120 vFabric SQLFire User's Guide Starting SQLFire Servers with the FabricServer Interface sqlfire.drda.traceAll sqlfire.drda.traceDirectory Example The following sample code shows how to start a Network Listener after specifying several properties. import com.vmware.sqlfire.*; // start a fabricserver if not running already. FabricServer fserver = FabricServiceManager.getFabricServerInstance(); if (fserver.status() != FabricService.State.RUNNING) { Properties props = new Properties(); props.setProperty("mcast-port", "23342"); props.setProperty("conserve-sockets", "false"); props.setProperty("log-level", "fine"); props.setProperty("host-data", "true"); fserver.start(props); } // commonly used network server properties Properties netprops = new Properties(); netprops.setProperty("sqlfire.drda.minThreads", "10"); netprops.setProperty("sqlfire.drda.maxThreads", "100"); netprops.setProperty("sqlfire.drda.keepAlive", "1000"); netprops.setProperty("sqlfire.drda.sslMode" , "off"); // Other possible values // are "basic" for encryption // only with no client // authentication, and // "peerAuthentication" // for encryption with // SSL clients. // now start a network server listening on port 4343. NetworkInterface netserver = fserver.startNetworkServer("localhost", 4343, netprops); System.out.println("started network server properties with \n" + netserver.getSysinfo()); 121 Chapter 18 Developing Java Clients and Peers A Java application can use the JDBC thin client driver to connect to a SQLFire cluster and execute SQL statements. Or, a Java application can use the JDBC peer client driver to embed a SQLFire peer process and participate as a member of the cluster. Both drivers use the basic JDBC connection URL of jdbc:sqlfire: where: • jdbc: is the protocol. • sqlfire: is the subprotocol. Connect to a SQLFire Server with the Thin Client JDBC Driver The thin client driver class is packaged in com.vmware.sqlfire.jdbc.ClientDriver. In addition to the basic JDBC Connection URL, you specify the host and port number of a SQLFire server or a locator to which the thin client driver will connect. For example: jdbc:sqlfire://myHostName:1527/ • Code Example on page 123 • Thin Client Failover on page 124 • Enabling Single-Hop Data Access on page 124 • Configuring TCP Keepalive Settings on page 125 • Thin Client Driver Limitations on page 125 Code Example This code sample shows a more complete example of connecting to a SQLFire server in a Java application: try { java.util.Properties p = new java.util.Properties(); // 1527 is the default port that a SQLFire server uses to listen for thin client connections Connection conn = DriverManager.getConnection("jdbc:sqlfire://myHostName:1527/"); // do something with the connection } catch (SQLException ex) { // handle any errors System.out.println("SQLException: " + ex.getMessage()); System.out.println("SQLState: " + ex.getSQLState()); 123 Developing Applications with SQLFire System.out.println("VendorError: " + ex.getErrorCode()); } Thin Client Failover When you use the thin client to connect to a SQLFire locator member (rather than directly to a SQLFire server), the thin client driver can provide automatic failover if the initial connection to the distributed system is lost. See sqlf locator on page 391. Note, however, that this assumes the initial connection to the specified SQLFire locator succeeds. To improve the chances of establishing an initial connection to a SQLFire system, you can optionally specify the address of a secondary locator in addition to the primary locator, using the secondary-locators connection property. For example: jdbc:sqlfire://myLocatorAddress:1527/;secondary-locators=mySecondaryLocatorAddress:1527 Enabling Single-Hop Data Access By default, using the thin-client driver provides either one-hop or two-hop access to the data for executing queries or DML statements. One-hop access is available if the client's SQL statements work against data that happens to reside on the SQLFire member to which the thin client has connected. All other cases result in one-hop or two-hop access to the data: the SQL statement is evaluated first on the SQLFire member to which the client is connected, and if necessary, that server routes the query to other members in the cluster that host the actual data for the statement. SQLFire provides the option to provide single-hop access to data for certain queries when using a thin client connection. To use this option, set the single-hop-enabled connection property to true when connecting with the thin client driver. For example: jdbc:sqlfire://myHostName:1527/;single-hop-enabled=true Or, from within the sqlf utility: connect client 'myHostName:1527/;single-hop-enabled=true' Note: Single-hop access for thin clients requires SQLFire data store members in the distributed system to run a network server for direct client access. Configure each data store with network server functionality even if you use a locator for member discovery. See Starting a Network Server on page 120. Single-hop access is provided only for prepared statements. When you enable single-hop access on a connection and then prepare a prepared statement, the local SQLFire server adds data distribution information to other SQLFire server members in the response of the prepare message. When the prepared statement is executed, the client uses the added parameter and information fetched from the connected server to determine the exact SQLFire server on which it can find the data locally; it then directs the execution to that server. The following types of queries are good candidates for single-hop access: • Queries that have a WHERE clause on the partitioning columns of a table. • Primary key-based SELECT statements where the primary key is also the partitioning key. • IN-based WHERE clauses on partitioning columns. If the client cannot determine the location of the data based on the WHERE clause, then it defaults to standard two-hop execution. Single-hop execution is performed only when the client can be absolutely certain of the location of data that is touched by the query. Internally, the client JVM maintains a pool of connections that is shared by all of the prepared statements that might execute statements with single-hop access. For each SQLFire server, the client maintains a queue of connections that can grow to a maximum number of connection specified by the sqlfire.client.single-hop-max-connections system property. After this maximum number of connections has been created for a particular server, further single-hop executions must wait for a connection to become available in the queue. If the number of connections created for a particular SQLFire server has not reached the maximum, 124 vFabric SQLFire User's Guide Developing Java Clients and Peers then the client creates a new connection on the fly, uses it, and then returns it back to the connection. The default value for sqlfire.client.single-hop-max-connections is 5 connections per server. If you are developing a client that requires more concurrent connections per server for single-hop access, increase the maximum number of connections per server using the sqlfire.client.single-hop-max-connections system property. Note: To avoid degrading the performance of the network server, use the smallest number of concurrent single-hop threads that satisfy performance requirements. Configuring TCP Keepalive Settings By default, SQLFire servers use a TCP keepalive probe to help determine when clients have gone offline. SQLFire thin clients can also use these keepalive settings to accurately determine when a server has gone offline. The relevant configuration properties are: • keepalive-count on page 342 • keepalive-idle on page 342 • keepalive-interval on page 342 To use these properties with a SQLFire thin client, include the jna.jar library in your CLASSPATH. Note: Windows platforms do not support per-socket configuration for keepalive-count. As an alternative, you can configure a system-wide keepalive-count value in some versions of Windows. See http://msdn.microsoft.com/en-us/library/windows/desktop/dd877220%28v=vs.85%29.aspx. Windows Vista and later versions keep this value fixed at 10. Note: On Solaris platforms prior to r10, system-wide TCP keepalive settings must be changed to larger values (approximately 30 seconds) in order to detect server failures by clients and vice versa. See http://docs.oracle.com/cd/E19082-01/819-2724/fsvdg/index.html. This also applies to other non-Linux, non-Windows platforms. For example, see http://www-01.ibm.com/support/docview.wss?uid=swg21231084. Thin Client Driver Limitations When the default batching mode is enabled for transactions, SQLFire detects any conflicts in DML operations lazily. DML conflicts may be thrown by the system at some point later in the transaction (for example, even when executing queries or at commit time). You can configure SQLFire to immediately detect conflicts at operation time by setting the gemfire.tx-disable-batching system property to "true" on all data store members in the distributed system. Note: Enabling gemfire.tx-disable-batching can degrade performance significantly. Enable this option only after you have thoroughly tested the setting in your system and have determined that the performance tradeoff is necessary to provide immediate conflict detection with thin clients. If you use the thin client driver to perform an insert to table that has no primary key, an automatic retry of the insert due to a failover (available when connecting via a locator member) can result in duplicate rows being added to the table. The thin-client driver has the following limitations when the single-hop connection property is enabled: • Single-hop access is not provided when using transactions or WAN replication. Note: Do not enable single-hop access when using transactions or WAN configurations, as it can lead to unexpected behavior. 125 Developing Applications with SQLFire • Single-hop access is only supported for partitioned tables where the partitioning column(s) are of the basic data types: integer, long, double, decimal, char, varchar, and real. If a table is partitioned on a column having any other data type (like date, time, timestamp, blob, clob, and so forth), then queries on that tables are not considered for single-hop execution. • Single hop execution is attempted only for prepared statements, and not for simple statements. • Single hop execution is attempted only for SELECT, UPDATE and DELETE statements, but not for INSERT statements. • SQLFire does not support single-hop access for queries that require data from multiple data stores to be merged together. Typically, queries having aggregates like MAX, MIN, AVG, ORDER BY, and so forth are executed as if single-hop were disabled. If an aggregate query can provide all results from a single data store, then SQLFire provides single-hop access for the query. • Tables that have an expression resolver are not considered for single-hop access. Start a SQLFire Peer with the Peer Client JDBC Driver The peer client driver class is packaged in com.vmware.sqlfire.jdbc.EmbeddedDriver. In addition to the basic JDBC Connection URL, peer client driver connections require one or more boot and/or connection properties to configure the embedded SQLFire peer process for member discovery and other features. For example: jdbc:sqlfire:;mcast-port=33666;host-data=false The connection properties can be specified either in the connection URL or passed in the Properties parameter to the DriverManager.getConnection method. In the connection URL, you specify attributes as key=value pairs: [;attributes] preceded by and separated by semicolons. For more on these properties, see Configuration Properties on page 327. In this case, all peers, including peer clients and SQLFire servers, are part of the same distributed system, discovering each other using either locator(s) or multicast. SQL statements that you execute in the peer client have at most single-hop access to data in the distributed system. (The SQLFire JDBC thin-client driver also provides single-hop access to data for lightweight client applications.) Note: If you use peer clients in a SQLFire distributed system that also contains data stores, keep in mind that peer clients themselves cannot use disk stores or persist data. You must start data stores and locators before starting peer clients, because peer clients rely on data stores to persist data. See Peer Client Considerations for Persistent Data on page 92 for more information. This code sample shows a more complete example of starting a peer client in a Java application: try { java.util.Properties p = new java.util.Properties(); // Use the locator running on the local host with port 3340 for peer member discovery... Connection conn = DriverManager.getConnection("jdbc:sqlfire:;locators=localhost[3340];mcast-port=0;host-data=false"); // Alternatively, use multicast on port 33666 for peer member discovery... /* Connection conn = DriverManager.getConnection("jdbc:sqlfire:;mcast-port=33666;host-data=false"); */ // do something with the connection } catch (SQLException ex) { // handle any errors 126 vFabric SQLFire User's Guide Developing Java Clients and Peers System.out.println("SQLException: " + ex.getMessage()); System.out.println("SQLState: " + ex.getSQLState()); System.out.println("VendorError: " + ex.getErrorCode()); } Note: • Unlike Derby, SQLFire does not use a databaseName. Instead of a "database" the connection is to a distributed system. The distributed system is uniquely identified by either the mcast-port or the locators. See Configuration Properties on page 327. • The subprotocol in the URL sqlfire: ends with a colon (:) and the list of connection attributes starts with a semicolon (;). • Setting mcast-port to 0 without specifying locators starts a "loner" (single member) distributed system. See Configuration Properties on page 327. • The list of connection attributes is not parsed for correctness. If you pass an incorrect attribute, it is simply ignored. • Setting the host-data attribute to true (default) specifies that data should be hosted in this member. To avoid hosting data in a member, such as in a peer client, set host-date to false. 127 Chapter 19 Configuring SQLFire as a JDBC Datasource The SQLFire JDBC implementation enables you to use a distributed system as an embedded JDBC datasource in products such as WebLogic Server. Procedure Follow this general procedure when setting up SQLFire as a datasource in a third-party product: 1. For products such as WebLogic Server that provide datasource templates, select "Apache Derby" or "Other" as the database type if vFabric SQLFire is not explicitly supported. 2. Specify "sqlfire" as the database name. This represents a single SQLFire distributed system. (SQLFire does not contain multiple databases as in Apache Derby or other relational database systems.) 3. For the hostname and port, specify the hostname and port combination of a SQLFire locator or a SQLFire server. This is the same hostname and port combination you would use to connect as a client from the sqlf prompt. 4. For the database username and password, enter a valid username and password combination if you have enabled authentication in your system (using the -auth-provider property). If you have not configured authentication in SQLFire, specify "app" as both the username and password values, or any other temporary value. Note: SQLFire uses the username specified in the JDBC connection as the schema name when you do not provide the schema name for a database object. SQLFire uses "APP" as the default schema. If your system does not enable authentication, you can specify "APP" for both the username and password to maintain consistency with the default schema behavior. 5. For the driver class, specify: com.vmware.sqlfire.internal.jdbc.ClientDataSource 6. The JDBC URL that you specify must begin with jdbc:sqlfire://. Remove any template properties such as create=true if they are present in the URL or properties fields. In products such as WebLogic, you cannot specify JDBC connection properties for an embedded datasource as part of the JDBC URL. Instead, use the properties field and specify connectionAttributes using the format: connectionAttributes=attribute;attribute;... For example: connectionAttributes=mcast-address=239.192.81.1;mcast-port=10334 or connectionAttributes=locators=239.192.81.1;mcast-port=0 See also the Apache Derby documentation for EmbeddedDataSource. 129 Developing Applications with SQLFire 7. A process can connect to only one SQLFire distributed system at a time. If you want to connect to a different SQLFire distributed system, shut down the current embedded data source before re-connecting with a different datasource. 130 vFabric SQLFire User's Guide Chapter 20 Storing and Loading JAR Files in SQLFire Application logic, which can be used by SQL functions and procedures, includes Java class files stored in a JAR file format. Storing application JAR files in SQLFire simplifies application deployment, because it reduces the potential for problems with a user's classpath. SQLFire automatically loads installed JAR file classes into the class loader so that you can use them in your SQLFire applications and procedures. The JAR classes are available to all members of the SQLFire distributed system, including those that join the system at a later time. Note: Many of the topics in this section were adapted from the Apache Derby documentation source files, and are subject to the Apache license: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Class Loading Overview You store application classes, resources, and procedure implementations in SQLFire by installing one or more JAR files. After installing the JAR file, an application can then access the classes without having to be coded in a particular way. These are the basic steps for storing and using JAR files in SQLFire. Create JAR Files for Your Application When you create a JAR file for installation, include any Java classes that are intended for SQLFire class loading. This might include stored procedure or result processor implementations, as well as supporting classes. When you add classes to the JAR file, do not include: • The standard Java packages (java.*, javax.*) 131 Developing Applications with SQLFire SQLFire does not prevent you from storing these standard JAR files, but the classes are never loaded from the JAR file. • Classes that are supplied with your Java environment (for example, sun.*) SQLFire can load classes from any number of JAR files from any number of schemas. Create JAR files intended for SQLFire class loading in the same way that you would create a JAR file for including in a user's classpath. For example: jar cf travelagent.jar travelagent/*.class Different IDEs have tools to generate a list of contents for a JAR file based on your application. If your application requires classes from other JAR files, you have the following options: • Extract the required third-party classes from their JAR files, and include only those classes in your JAR file. Use this option when you need only a small subset of the classes in the third-party JAR file. • Store the entire third-party JAR file in the database. Use this option when you need most or all of the classes in the third-party JAR file, because you can then upgrade your application and third-party logic independently of one another. • Deploy the third-party JAR file in the user's class path. Use this option when the necessary classes are already installed on a user's computer. Manage JAR Files in SQLFire When you install a JAR file, you specify a unique SQLFire JAR name, which is a SQL92Identifier. SQLFire installs the JAR file and automatically loads the JAR file classes into its class loader, and it becomes available to all members of the distributed system (including members that join the system at a later time). SQLFire provides sqlf commands to install, replace, and remove JAR files as described in these sections: • Installing a JAR File on page 134 • Manage JAR Files in SQLFire on page 132 • Removing an Installed JAR File on page 135 Installing a JAR File To install a JAR file to a SQLFire distributed, use the sqlf install-jar command. For example, the following command installs the tours.jar file to the APP schema: sqlf install-jar -name=APP.toursjar -file=c:\tours.jar -client-bind-address=locator_address -client-port=locator_port If the SQLFire distributed system uses multicast for discovery instead of a locator, specify the multicast properties instead, as in: sqlf install-jar -name=toursjar -file=c:\tours.jar -mcast-address=multicast_address -mcast-port=multicast_port The -name that you provide for the JAR must be a unique identifier. You must include a schema name to qualify the identifier. You can use the identifier with later calls to sqlf replace-jar or sqlf remove-jar. The -file option specifies the location of the JAR file to install using either a local path or a URL. After installing the JAR to the distributed system, SQLFire automatically loads the JAR file classes into its class loader; you do not need to explicitly load classes after installing the JAR. The JAR and its classes are available to all members of the SQLFire distributed system, including those that later join the cluster. 132 vFabric SQLFire User's Guide Storing and Loading JAR Files in SQLFire Note: After you install a JAR file, you cannot modify any of the individual classes or resources within the JAR file. Instead, you must replace the entire JAR file to update a class. Replacing a JAR File Use the sqlf replace-jar command to replace an installed JAR file with a new JAR. Specify the identifier of an existing JAR installation when using the command, as in: sqlf replace-jar -name=APP.toursjar -file=c:\tours2.jar -client-bind-address=locator_address -client-port=locator_port When you replace a JAR file, SQLFire loads the new classes right away without your having to reboot. It also recompiles objects that depend on the JAR file, such as installed listener implementations. Removing an Installed JAR File Specify the JAR identifier with the sqlf remove-jar command to remove an installed JAR file. For example, the following command removes the class files associated with the APP.toursjar JAR installation: sqlf remove-jar -name=APP.toursjar -client-bind-address=locator_address -client-port=locator_port Code Your Applications In your SQLFire applications, you can load the installed classes either by indirectly referencing them in the code or by directly using java.lang.Class.forName. You load resources the way you normally would, using the standard java.lang.Class.getResourceAsStream, a mechanism that allows an application to access resources defined in the classpath without knowing where or how they are stored. You do not need to make any changes to the way code interacts with SQLFire and its JDBC driver. An application can safely attempt to boot SQLFire, even though it is already running, without any errors. Applications connect to SQLFire in the usual manner. Note: The method getResource is not supported. Alternate Methods for Managing JAR Files SQLFire also provides system procedures that you can use to interactively install and manage JAR files from a client connection. Keep in mind that the procedures have certain limitations compared to using sqlf commands to manage JAR files. This topic contains the following sections: • Restrictions for Managing JAR Files Using System Procedures on page 134 • Installing a JAR File on page 134 • Installing a JAR File Directly into SYS.JARS on page 134 • Replacing a JAR File on page 135 • Removing an Installed JAR File on page 135 See also JAR Installation Procedures on page 623 for more information about the procedures used to manage installed JAR files. 133 Developing Applications with SQLFire Restrictions for Managing JAR Files Using System Procedures To use the SQLJ.INSTALL_JAR or SQLJ.REPLACE_JAR procedure, the JAR file path must be available on the specific SQLFire data store to which the client is connected. If the client connects directly to a known SQLFire server, then only that server requires the JAR file to be available at the specified path when the procedure executes. However, if the client connects using a locator then it may be connected to any available server in the distributed system. In this case, the JAR file path should be available to all members of the SQLFire cluster (for example, from a fileshare location such as z:\) to ensure that the procedure can execute. Note: If you cannot provide a common JAR location to ensure that SQLJ.INSTALL_JAR or SQLJ.REPLACE_JAR executes, use the sqlf commands described in Manage JAR Files in SQLFire on page 132 or manually inject the JAR file into the SQLFire system as described in Installing a JAR File Directly into SYS.JARS on page 134 . Installing a JAR File with SQLJ.INSTALL_JAR To install a JAR file to SQLFire, connect to a SQLFire member and execute the install_jar procedure. For example, the following procedure installs the tours.jar file to the APP schema, from a fileshare location: call sqlj.install_jar( 'z:\tours.jar', 'APP.Sample1', 0) Note: The final integer argument specifies an alias for the JAR file. However, SQLFire ignores this argument, so it is normally set to 0. The second argument defines an identifier for the JAR file in the SQLFire system. You must include a schema name to qualify the identifier. You can use the JAR identifier at a later time with the SQLJ.REPLACE_JAR and SQLJ.REMOVE_JAR procedures. You can optionally specify a quoted identifier for the SQLFire JAR name: call sqlj.install_jar( 'z:\tours.jar', 'APP."Sample2"', 0) After installing the JAR, SQLFire automatically loads the JAR file classes into its class loader; you do not need to explicitly load classes after installing the JAR. The JAR and its classes are available to all members of the SQLFire distributed system, including those that later join the cluster. Note: After you install a JAR file, you cannot modify any of the individual classes or resources within the JAR file. Instead, you must replace the entire JAR file to update a class. Installing a JAR File Directly into SYS.JARS If the JAR file to install is not available to every data store member in the SQLFire cluster, inject the JAR file directly from the client into the SQLFire system using Java code. The SYS.JARS table stores installed JAR files, and you can insert a new JAR into this table as a byte[] value. For example, an application can use code similar to the following to add a JAR to the SYS.JARS table: byte[] jarBytes = getJarBytes(myjar); String sql = "insert into SYS.JARS values(?, ?)"; PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1, "app.sample1"); ps.setBytes(2, jarBytes); ps.executeUpdate(); 134 vFabric SQLFire User's Guide Storing and Loading JAR Files in SQLFire In this example application, the getJarBytes() method would be implemented in the following way: public static byte[] getJarBytes(String jar) throws Exception { FileInputStream fis = new FileInputStream(jar); byte[] data = new byte[4096]; int len; ByteArrayOutputStream bos = new ByteArrayOutputStream(); while ((len = fis.read(data)) != -1) { bos.write(data, 0, len); } return bos.toByteArray(); } SQLFire automatically loads the installed JAR file class into its class loader; you do not need to explicitly load classes after installing the JAR. Replacing a JAR File with SQLJ.REPLACE_JAR Execute the SQLJ.REPLACE_JAR procedure on a SQLFire member to replace a JAR file. For example, the following procedure replaces the JAR contents of the loaded APP.Sample1 JAR installation with the contents of the newtours.jar file. call sqlj.replace_jar( 'c:\myjarfiles\newtours.jar', 'APP.Sample1'); When you replace a JAR file, SQLFire loads the new classes right away without your having to reboot. Removing an Installed JAR File with SQLJ.REMOVE_JAR Execute the SQLJ.REMOVE_JAR procedure on a SQLFire member to remove an installed JAR file. For example, the following command removes the class files associated with the APP.Sample1 JAR installation: call sqlj.remove_jar( 'APP.Sample1', 0); Note: The final integer argument specifies an alias for the JAR file. However, SQLFire ignores this argument, so it is normally set to 0. 135 Chapter 21 Developing ADO.NET Client Applications SQLFire provides a managed ADO.NET driver that you can use to develop non-Java client applications. The ADO.NET driver uses IKVM technology to translate SQLFire JDBC core libraries into .NET MSIL. The driver is supported with the Microsoft .NET 2.0 SP1 or higher framework. Note: You cannot register a custom .NET type as a user-defined type in SQLFire. About the ADO.NET Driver The SQLFire ADO.NET driver is an implementation of Microsoft's ADO.NET interfaces and abstract classes. It provides connectivity to a SQLFire system as a network client driver. In this release of SQLFire, the ADO.NET driver does not support running a SQLFire member in an embedded mode (embedded driver) within an application. The driver provides fast access to a SQLFire cluster from .NET clients and enables advanced SQLFire features such as: • Transparent access to partitioned or replicated data in the cluster • High availability • Distributed queries and transactions You can access the driver through any .NET language including C#, C++/CLI, and Visual Basic .NET. As with the JDBC network driver, the ADO.NET driver complies with the DRDA standard protocol and utilizes several SQLFire extensions to provide enhanced features. The following sections provide more information about the ADO.NET driver: • High Availability on page 137 • Load Balancing on page 138 • Extensions for Batching and Row Locking on page 138 High Availability The ADO.NET driver maintains information about the servers available in a SQLFire cluster. If the server to which the client is connected goes down, then the driver automatically re-routes the connection to another server available in the cluster. To take full advantage of this feature, clients should connect using the address of a stand-alone SQLFire locator rather than a SQLFire server, because locators provide more accurate information about the available servers to which a client can fail over. If you specify the address of a server rather than a stand-alone locator, then it is possible that the client will fail to find any available server if those servers have been taken offline. Note: The automatic failover feature assumes the client's initial connection to the specified SQLFire locator succeeds. To impr the chances of establishing an initial connection to a SQLFire system, you can optionally specify the address of a secondary loca 137 Developing Applications with SQLFire in addition to the primary locator, using the secondary-locators connection property. For example, use a conne similar to "server=primary-locator-address:port;secondary-locators=secondary-locator-addre when you initiate a connection using the ADO.NET driver. If the application is not executing a transaction, then failover occurs transparently to the application. Failed operations are automatically re-executed if necessary. The application does not receive any exceptions as long as at least one server is available in the cluster to service network clients. However, when querying LOB data-types (BLOB/CLOB), clients may receive an SQLFException with State "XJ217" due to the LOB handle not being found on the new server. In this case, the client may need to retry the query explicitly (issue #43253 in vFabric SQLFire Limitations on page 765 provides more details). In this release of SQLFire, if the application is in the middle of a transaction and the server to which client is connected fails, then the current transaction fails with a connection exception (SQLFException with State "08006") and the application must re-execute the transaction. To handle such a case, applications can create a new connection, and then begin a new transaction and retry the transaction. Load Balancing When using the SQLFire locator or a locator embedded inside a server, servers inform the active locator of the load on each server using the number of current client connections on the server. This allows the locator to determine the best server to use for a new client connection. In this way, a network client that connects using a locator is always directed to the least-loaded server in the cluster. Extensions for Batching and Row Locking Similar to the JDBC API, the ADO.NET driver provides extensions to the DbCommand API to allow for batching without requiring a DbDataAdapter. Also, the DbDataReader implementation, SQLFDataReader, allows for expressing the intent to lock rows when executing a SELECT … FOR UPDATE statement. Additional extensions from the JDBC API are also provided, such as SQLFConnection.AutoCommit. ADO.NET Driver Classes All ADO.NET driver implementation classes reside in the VMware.Data.SQLFire namespace. 138 SQLFire ADO.NET Class Description More Information SQLFBatchUpdateException Thrown when a batch operation fails. • VMware.Data.SQLFire.BatchUpdateException on page 743 Extends SQLFException. SQLFClientConnection Creates a connection to SQLFire with • Connecting to SQLFire with the ADO.NET Driver on page 140 a URL of the form "Server=:" . • Managing SQLFire Transactions on page 147 Provides several extension methods to • Performing Batch Updates on page 148 • VMWare.Data.SQLFire.SQLFClientConnection on page support SQLFire transactions. 743 SQLFCommand Implements the .NET System.Data.Common.DbCommand class. • Executing SQL Commands on page 141 • Working with Result Sets on page 141 • Specifying Command Parameters with SQLFParameter on page 144 • VMware.Data.SQLFire.SQLFCommand on page 748 • System.Data.Common.DbCommand (.NET) vFabric SQLFire User's Guide Developing ADO.NET Client Applications SQLFire ADO.NET Class Description More Information SQLFType SQLFire types. Each type corresponds • java.sql.Types to a JDBC type. • VMware.Data.SQLFire.SQLFType on page 754 SQLFDataReader • Working with Result Sets on page 141 Implements the .NET System.Data.Common.DbDataReader • VMware.Data.SQLFire.SQLFDataReader on page 757 class. • System.Data.Common.DbDataReader (.NET) SQLFDataAdapter • Storing a Table on page 142 Implements the .NET System.Data.Common.DbDataAdapter • Storing Multiple Tables on page 143 class. • Updating Row Data on page 145 SQLFDataAdapter uses batch • Adding Rows to a Table on page 146 • VMware.Data.SQLFire.SQLFDataAdapter on page 755 updates when the UpdateBatchSize property is set to a value greater than one. SQLFCommandBuilder • Updating Row Data on page 145 Implements the .NET System.Data.Common.DbCommandBuilder • Adding Rows to a Table on page 146 class. Use this class to generate • VMware.Data.SQLFire.SQLFCommandBuilder on page commands with SQLFDataAdapter. 754 • System.Data.Common.DbDataAdapter (.NET) SQLFParameter Implements the .NET System.Data.Common.DbParameter class. SQLFParameterCollection • Specifying Command Parameters with SQLFParameter Implements the .NET System.Data.Common.DbParameterCollection on page 144 class. • VMware.Data.SQLFire.SQLFParameterCollection on page 760 • System.Data.Common.DbParameterCollection (.NET) SQLFTransaction • Managing SQLFire Transactions on page 147 Implements the .NETSystem.Data.Common.DbTransaction • VMware.Data.SQLFire.SQLFTransaction on page 761 class. SQLFire currently supports only • System.Data.Common.DbTransaction (.NET) the READ_COMMITTED isolation level. SQLFException • VMware.Data.SQLFire.SQLFException on page 759 Extends the System.Data.Common.DbException • System.Data.Common.DBException (.NET) class. This exception is thrown for all • JDBC API Javadoc SQLFire exceptions. It exposes additional State and Severity properties that have the same meanings as in the JDBC API. • Specifying Command Parameters with SQLFParameter on page 144 • VMware.Data.SQLFire.SQLFParameter on page 760 • System.Data.Common.DbParameter (.NET) Installing and Using the ADO.NET driver Follow this procedure to install and use the SQLFire ADO.NET driver. 1. Add a reference to your project in the VMware.Data.SQLFire.dll. This DLL is installed in the vFabric_SQLFire_11_bNNNNN\adonet\lib directory. 139 Developing Applications with SQLFire 2. Reference the driver namespace in each source file where you want to use SQLFire components. For example, include this directive with all other references required in your application: using VMware.Data.SQLFire; Connecting to SQLFire with the ADO.NET Driver Use the SQLFClientConnection class to create a new connection to a SQLFire cluster. You must specify a connection URL of the form "server=hostname:port". For example: string sqlfHost = "localhost"; int sqlfPort = 1527; string connectionStr = string.Format(@"server={0}:{1}", sqlfHost, sqlfPort); SQLFClientConnection connection = null; try { // Initialize and open connection connection = new SQLFClientConnection(connectionStr); connection.Open(); /// /// Execute SQLFire commands /// } catch (Exception e) { /// /// Log or re-throw exception /// } finally { connection.Close(); } This creates a client connection to a SQLFire server running on the local machine and listening on the default port 1527. After you obtain a connection you can execute DDL and DML statements as necessary. Managing Connections In this release of SQLFire, the VMWare.Data.SQLFire.SQLFClientConnection class and underlying driver do not maintain any implicit pool of connections. Creating a new client connection to a SQLFire cluster is a somewhat expensive operation, so use connection resources carefully. There are two possible approaches for managing connections: • Use a custom pool of connections. The pool can be maintained as a thread-safe bounded queue of available connections. When a module is done with the connection, it can return the connection to the queue. If many connections are lying idle in the pool for some time, those connections can be cleaned up. This approach requires some work to implement, but tuning a connection pool for application requirements generally provides the best performance and resource utilization. • Use a thread-local connection. This approach relies on having a connection in the thread local (ThreadStatic attribute), so that all modules can access the connection quickly without having to create it explicitly. The advantage of this approach is that applications do not need to pass the connection object to all of the modules that require access. Each module can obtain the ThreadStatic connection when required. Although this approach 140 vFabric SQLFire User's Guide Developing ADO.NET Client Applications is easier to implement, it is useful only in scenarios where an application has a fixed set of threads, or long-lived threads that operate against a SQLFire system. Executing SQL Commands To execute a SQL command, create a SQLFCommand from the SQLFire connection and supply the text of a SQL command. For example: string sqlfHost = "localhost"; int sqlfPort = 1527; string connectionStr = string.Format(@"server={0}:{1}", sqlfHost, sqlfPort); SQLFClientConnection connection = null; try { connection = new SQLFClientConnection(connectionStr); SQLFCommand command = connection.CreateCommand(); command.CommandType = CommandType.Text; command.CommandText = "SELECT COUNT(*) FROM product"; connection.Open(); int prodCount = Convert.ToInt32(command.ExecuteScalar()); } catch (Exception e) { /// /// Log or re-throw exception /// } finally { connection.Close(); } Working with Result Sets SQLFDataReader helps you work with multiple rows that are returned from a SQL statement. The following example queries all rows from a sample table and stores the results in a SQLFDataReader object. The application then accesses and displays each row in the result set. string sqlfHost = "localhost"; int sqlfPort = 1527; string connectionStr = string.Format(@"server={0}:{1}", sqlfHost, sqlfPort); SQLFClientConnection connection = null; try { connection = new SQLFClientConnection(connectionStr); SQLFCommand command = connection.CreateCommand(); command.CommandType = CommandType.Text; command.CommandText = "SELECT * FROM product"; connection.Open(); 141 Developing Applications with SQLFire SQLFDataReader reader = command.ExecuteReader(); StringBuilder row = new StringBuilder(); while (reader.Read()) { for (int i = 0; i < reader.FieldCount; i++) row.AppendFormat("{0}, ", reader.GetString(i)); Console.WriteLine(row.ToString()); } } catch (Exception e) { /// /// Log or re-throw exception /// } finally { connection.Close(); } Storing a Table You can use SQLFDataAdapter to populate a System.Data.DataTable object with the results from a SQL command, or to refresh a DataTable object with new results. The following example fills a DataTable with rows retrieved from a table, and then uses the DataTable to display each row. string sqlfHost = "localhost"; int sqlfPort = 1527; string connectionStr = string.Format(@"server={0}:{1}", sqlfHost, sqlfPort); SQLFClientConnection connection = null; try { connection = new SQLFClientConnection(connectionStr); SQLFCommand command = connection.CreateCommand(); command.CommandType = CommandType.Text; command.CommandText = "SELECT * FROM product"; connection.Open(); // Create adapter and populate the DataTable object SQLFDataAdapter adapter = command.CreateDataAdapter(); DataTable table = new DataTable("product"); adapter.Fill(table); // Parse the DataTable object by rows foreach (DataRow row in table.Rows) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < row.Table.Columns.Count; i++) sb.AppendFormat("{0}, ", (row[i].ToString())); Console.WriteLine(sb.ToString()); 142 vFabric SQLFire User's Guide Developing ADO.NET Client Applications } } catch (Exception e) { /// /// Log or re-throw exception /// } finally { connection.Close(); } Storing Multiple Tables You can use SQLFDataAdapter with a System.Data.DataSet object to hold multiple result sets. The following example uses a dataset to store the full contents from three different tables. string sqlfHost = "localhost"; int sqlfPort = 1527; string connectionStr = string.Format(@"server={0}:{1}", sqlfHost, sqlfPort); SQLFClientConnection connection = null; try { connection = new SQLFClientConnection(connectionStr); SQLFCommand command = connection.CreateCommand(); command.CommandType = CommandType.Text; connection.Open(); // Create adapter and data set to hold multiple result sets SQLFDataAdapter adapter = command.CreateDataAdapter(); DataSet dataset = new DataSet("CustomerOrder"); // Retrieve all customer records command.CommandText = "SELECT * FROM customer"; adapter.Fill(dataset, "customer"); // Retrieve all order records command.CommandText = "SELECT * FROM orders"; adapter.Fill(dataset, "orders"); // Retrieve all orderdetail records command.CommandText = "SELECT * FROM orderdetail"; adapter.Fill(dataset, "orderdetail"); // Parse all tables and rows in the data set foreach (DataTable table in dataset.Tables) { foreach (DataRow row in table.Rows) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < row.Table.Columns.Count; i++) sb.AppendFormat("{0}, ", (row[i].ToString())); Console.WriteLine(sb.ToString()); 143 Developing Applications with SQLFire } } } catch (Exception e) { /// /// Log or re-throw exception /// } finally { connection.Close(); } Specifying Command Parameters with SQLFParameter Use SQLFParameter and SQLFParameterCollection to define input parameters for a SQLFCommand object. You do not need to specify the size of variable-sized data or scale and precision for numeric data. The only case where size specification can be useful is when data must be truncated to the given size. In all other cases the driver or server determines the data size. This applies to both input as well as output parameters. For the latter case, the driver sets the correct size, precision, scale as appropriate. The following example adds two SQLFParameter objects to a SQLFCommand parameter collection, and then uses the command to create an SQLFDataAdapter. string sqlfHost = "localhost"; int sqlfPort = 1527; string connectionStr = string.Format(@"server={0}:{1}", sqlfHost, sqlfPort); SQLFClientConnection connection = null; try { // Initialize and open connection connection = new SQLFClientConnection(connectionStr); connection.Open(); SQLFCommand command = connection.CreateCommand(); command.CommandType = CommandType.Text; command.CommandText = @"SELECT * FROM orders WHERE order_date = ? AND subtotal > ?"; // Insert order_date value and add to command’s Parameters collection SQLFParameter param1 = Command.CreateParameter(); param1.DbType = DbType.Date; param1.Value = DateTime.Today; Command.Parameters.Add(param1); // Insert subtotal value add to command’s Parameters collection SQLFParameter param2 = Command.CreateParameter(); param2.DbType = DbType.Decimal; param2.Value = 999.99; Command.Parameters.Add(param2); SQLFDataAdapter adapter = command.CreateDataAdapter(); DataTable table = new DataTable("orders"); adapter.Fill(table); } catch (Exception e) 144 vFabric SQLFire User's Guide Developing ADO.NET Client Applications { /// /// Log or re-throw exception /// } finally { connection.Close(); } You can also specify a range of parameters as an array of objects, as shown in this example: string sqlfHost = "localhost"; int sqlfPort = 1527; string connectionStr = string.Format(@"server={0}:{1}", sqlfHost, sqlfPort); SQLFClientConnection connection = null; try { // Initialize and open connection connection = new SQLFClientConnection(connectionStr); connection.Open(); SQLFCommand command = connection.CreateCommand(); command.CommandType = CommandType.Text; command.CommandText = @"SELECT * FROM orders WHERE order-date = ? AND subtotal > ?"; // Create an object array containing parameters' value object[] parameters = new object[] { DateTime.Today, 999.99 }; // Add object array as parameters (range) command.Parameters.AddRange(parameters); SQLFDataAdapter adapter = command.CreateDataAdapter(); DataTable table = new DataTable("orders"); adapter.Fill(table); } catch (Exception e) { /// /// Log or re-throw exception /// } finally { connection.Close(); } Updating Row Data You can use SQLFCommandBuilder to update, delete, and insert rows that are stored in a SQLFDataAdapter object. The following example uses an SQLFDataAdapter object to store the contents of a table, and then update row data. string sqlfHost = "localhost"; int sqlfPort = 1527; string connectionStr = string.Format(@"server={0}:{1}", sqlfHost, sqlfPort); 145 Developing Applications with SQLFire SQLFClientConnection connection = null; try { connection = new SQLFClientConnection(connectionStr); SQLFCommand command = connection.CreateCommand(); command.CommandType = CommandType.Text; command.CommandText = @"SELECT unit_cost, retail_price FROM product WHERE product_id="; connection.Open(); // Create adapter and populate the DataTable object SQLFDataAdapter adapter = command.CreateDataAdapter(); DataTable table = new DataTable("product"); adapter.Fill(table); // Generate update command SQLFCommandBuilder builder = new SQLFCommandBuilder(adapter); adapter.UpdateCommand = builder.GetUpdateCommand(); // Modify product pricing table.Rows[0]["unit_cost"] = 99.99; table.Rows[0]["retail_price"] = 199.99; // Update the underlying table adapter.Update(table); } catch (Exception e) { /// /// Log or re-throw exception /// } finally { connection.Close(); } Adding Rows to a Table You can use SQLFCommandBuilder to update, delete, and insert rows that are stored in an SQLFDataAdapter object. The following example uses a SQLFDataAdapter object to store the contents of a table, and then insert new rows. string sqlfHost = "localhost"; int sqlfPort = 1527; string connectionStr = string.Format(@"server={0}:{1}", sqlfHost, sqlfPort); SQLFClientConnection connection = null; try { connection = new SQLFClientConnection(connectionStr); SQLFCommand command = connection.CreateCommand(); command.CommandType = CommandType.Text; 146 vFabric SQLFire User's Guide Developing ADO.NET Client Applications command.CommandText = @"SELECT * FROM product"; connection.Open(); // Create adapter and populate the DataTable object SQLFDataAdapter adapter = command.CreateDataAdapter(); DataTable table = new DataTable("product"); adapter.Fill(table); // Generate update command SQLFCommandBuilder builder = new SQLFCommandBuilder(adapter); adapter.InsertCommand = builder.GetInsertCommand(); // Create new product row DataRow row = table.NewRow(); row[0] = ; row[1] = <...>; row[2] = <...>; ... // Update the underlying table adapter.Update(table); } catch (Exception e) { /// /// Log or re-throw exception /// } finally { connection.Close(); } Managing SQLFire Transactions SQLFClientConnection implements methods to help you delimit SQLFire transactions in your application code. You begin and commit transactions using the connection object itself. The following example uses an SQLFDataAdapter object to insert and update table data within as a single transaction. string sqlfHost = "localhost"; int sqlfPort = 1527; string connectionStr = string.Format(@"server={0}:{1}", sqlfHost, sqlfPort); SQLFClientConnection connection = null; try { // Open connection, disable auto-commit, and start transaction connection = new SQLFClientConnection(connectionStr); connection.AutoCommit = false; connection.BeginSQLFTransaction(IsolationLevel.ReadCommitted); SQLFCommand command = connection.CreateCommand(); command.CommandType = CommandType.Text; connection.Open(); // Get product info 147 Developing Applications with SQLFire command.CommandText = "SELECT * FROM product WHERE product_id=?"; SQLFDataAdapter adapter = command.CreateDataAdapter(); DataTable table = new DataTable("product"); adapter.Fill(table); // Create new order command.CommandText = "INSERT INTO orders VALUES(?, ?, ?, ?, ?)"; command.ExecuteNonQuery(); // Create new order detail command.CommandText = "INSERT INTO orderdetail VALUES(?, ?, ?, ?, ?)"; command.ExecuteNonQuery(); // Update product quantity command.CommandText = "UPDATE product SET quantity=? WHERE product_id=?"; command.ExecuteNonQuery(); // Commit transaction connection.Commit(); } catch (Exception e) { /// /// Log or re-throw exception /// } finally { connection.Close(); } Performing Batch Updates The SQLFCommand object provides AddBatch(), ExecuteBatch(), and ClearBatch() methods to explicitly perform batch updates. The result of ExecuteBatch() is the number of rows changed by each command in a batch. This example uses SQLFire batch operations to insert new table rows. int numRecords = 100; int batchSize = 10; // Limit number of statements per batch execution string sqlfHost = "localhost"; int sqlfPort = 1527; string connectionStr = string.Format(@"server={0}:{1}", sqlfHost, sqlfPort); SQLFClientConnection connection = null; try { connection = new SQLFClientConnection(connectionStr); connection.Open(); SQLFCommand command = connection.CreateCommand(); command.CommandType = CommandType.Text; command.CommandText = @"INSERT INTO orders(order_id, order_date, ship_date, customer_id, subtotal) VALUES(?, ?, ?, ?, ?)"; // Prepare batch statement 148 vFabric SQLFire User's Guide Developing ADO.NET Client Applications command.Prepare(); int stCount = 0; // batch statements count for (int i = 0; i < numRecords; i++) { command.Parameters[0] = ; command.Parameters[1] = ; command.Parameters[2] = ; command.Parameters[3] = ; command.Parameters[4] = ; // Add statement to command's batch command.AddBatch(); // Execute Batch statements when batch size is reached and reset if ((++stCount) == batchSize) { command.ExecuteBatch(); stCount = 0; } } // Execute the remaining statements in the batch command.ExecuteBatch(); } catch (Exception e) { /// /// Log or re-throw exception /// } finally { connection.Close(); } Generic Coding with the SQLFire ADO.NET Driver This release of the ADO.NET driver does not support DbProviderFactory. However, all implementation classes extend the corresponding classes in the System.Data.Common namespace. This allows applications to use the base classes of that namespace in the code and resort to SQLFire-specific classes only for creating class objects, or when SQLFire-specific methods must be invoked. If an application creates a SQLFClientConnection explicitly, then it can continue to use the base DbConnection class as far as possible. The classes VMWare.Data.SQLFire.SQLFClientConnection, VMware.Data.SQLFire.SQLFDataAdapter and VMware.Data.SQLFire.SQLFCommandBuilder require explicit creation, while the remaining class objects can be obtained using the base classes of the System.Data.Common namespace. For example, you need not create the SQLFCommand object explicitly because the DbConnection.CreateCommand() method provides a base DbCommand object. (This object is actually a SQLFCommand when it is using a SQLFClientConnection object.) Applications should use the base classes from the System.Data.Common namespace when writing ADO.NET code that can be easily changed to use a different driver, or when multiple drivers are used from the same code base. The table shows the mapping of the SQLFire ADO.NET driver classes to their base classes in the System.Data.Common namespace that you should use for generic coding. Also listed are the interfaces in System.Data implemented by the class. 149 Developing Applications with SQLFire Table 4: Mapping SQLFire driver classes to System.Data.Common base classes SQLFire ADO.NET Driver Class ADO.NET base class (in System.Data.Common) ADO.NET interfaces (in System.Data) SQLFClientConnection DbConnection IDbConnection SQLFCommand DbCommand IDbCommand SQLFCommandBuilder DbCommandBuilder n/a SQLFDataAdapter DbDataAdapter IDbDataAdapter SQLFDataReader DbDataReader IDataReader SQLFException DbException n/a SQLFParameter DbParameter IDataParameter, IDbDataParameter SQLFParameterCollection DbParameterCollection IDataParameterCollection SQLFRowUpdatedEventArgs RowUpdatedEventArgs n/a SQLFRowUpdatingEventArgs RowUpdatingEventArgs n/a SQLFTransaction DbTransaction IDbTransaction SQLFType (use DbTypes as in Table 88: SQL types to SQLFType mapping on page 754) See VMware.Data.SQLFire.SQLFType on page 754. For example: // Open a new connection to the network server running on localhost:1527 string host = "localhost"; int port = 1527; string connectionStr = string.Format("server={0}:{1}", host, port); // use the SQLFire specific class for connection creation using (SQLFClientConnection conn = new SQLFClientConnection(connectionStr)) { conn.Open(); // create a table // using the base DbCommand class rather than SQLFire specific class DbCommand cmd = conn.CreateCommand(); cmd.CommandText = "create table t1 (id int primary key, addr varchar(20))"; cmd.ExecuteNonQuery(); // insert into the table using named parameters // using an abstracted method that can deal with difference in the // conventions of named parameters in different drivers cmd = conn.CreateCommand(); string idPrm = GetEscapedParameterName("ID"); string addrPrm = GetEscapedParameterName("ADDR"); cmd.CommandText = "insert into t1 values (" + idPrm + "," + addrPrm + ")"; cmd.Prepare(); // using the base DbParameter class DbParameter prm; for (int i = 0; i < 1000; i++) { // first the parameter for ID cmd.Parameters.Clear(); prm = cmd.CreateParameter(); prm.ParameterName = "ID"; prm.DbType = DbType.Int32; prm.Value = i; 150 vFabric SQLFire User's Guide Developing ADO.NET Client Applications cmd.Parameters.Add(prm); // next the parameter for ADDR prm = cmd.CreateParameter(); prm.ParameterName = "ADDR"; prm.DbType = DbType.String; prm.Value = "addr" + i; cmd.Parameters.Add(prm); cmd.ExecuteNonQuery(); } // drop the table cmd = conn.CreateCommand(); cmd.CommandText = "drop table t1"; cmd.ExecuteNonQuery(); conn.Close(); } 151 Chapter 22 Using SQLFire.NET Designer The SQLFire.NET Designer component provides Visual Studio 2008 design-time support for a SQLFire distributed system. After installing the Designer component you can add SQLFire databases to the Server Explorer list in Visual Studio 2008, design queries with the Query Designer, drag-and-drop tables onto a typed DataSet, and so forth. The Designer component also enables you to create and edit SQLFire schemas directly in Visual Studio 2008. Installing SQLFire.NET Designer The vFabric SQLFire installation provides an installation program to install and register the SQLFire.NET component. Prerequisites In order to install or use SQLFire.NET Designer, you must install this software in addition to vFabric SQLFire: • Microsoft Visual Studio 2008 • Microsoft Visual Studio 2008 SP1 • Microsoft Visual Studio 2008 SDK Procedure To install the SQLFire.NET component: 1. Go to the \adonet\SQLFireDesigner subdirectory of your vFabric SQLFire installation. (For example, c:\vFabric_SQLFire_11_bNNNNN\adonet\SQLFireDesigner). 2. Double-click the sqlfire_setup.msi installer. 3. Follow the on-screen prompts to install SQLFire.NET Designer. Connecting to a SQLFire Distributed System Use SQLFire.NET Designer to create, modify and delete connections to vFabric SQLFire distributed systems. Prerequisites Before you follow this procedure: • Install the SQLFire.NET Designer component. See Installing SQLFire.NET Designer on page 153. • Start at least one SQLFire member with client access. See Tutorials on page 43. Procedure To connect to a SQLFire system: 153 Developing Applications with SQLFire 1. Start Visual Studio 2008. 2. Select View > Server Explorer to open the Server Explorer window. 3. Right-click the Data Connections node and choose Add Connection.... to display the Add Connection dialog. 4. Click Change... to display the Change Data Source dialog. 5. In the Data provider menu, select .NET Framework Data Provider for SQLFire and click OK. 6. In the Server field, anter the hostname and port of the SQLFire server or locator to which you want to connect (for example, localhost:1527). 7. Click Test Connection to verify that you can connect to the SQLFire system. 8. Click OK to create the connection. A SQLFire node is added to the Data Connections node. The connection settings are saved for future use. You can use the saved connection to design or edit tables, columns, indexes, foreign keys, constraints, views, and triggers. Editing Tables Use SQLFire.NET Designer to visually create and modify SQLFire tables. Prerequisites Before you follow this procedure: • Install the SQLFire.NET Designer component. See Installing SQLFire.NET Designer on page 153. • Create a connection to a SQLFire system in Visual Studio 2008. See Connecting to a SQLFire Distributed System on page 153. Procedure To design SQLFire tables with SQLFire.NET Designer: 1. 2. 3. 4. 5. 6. Start Visual Studio 2008. Select View > Server Explorer to open the Server Explorer window. Right-click the Data Connections > SQLFire node. To create a new table, right-click the Tables folder and select Add New Table to open the Table Designer. To edit an existing table, right-click an available table name and select Design to open the Table Designer. The Table Designer view provides several features to help you edit SQLFire tables: • Column editor grid—Use the column editor grid at the top of the view to add, delete, or rearrange table columns. Enter column names and data types directly in the labeled cells. Choose Allow Nulls if the column should allow null values. Click the cell to the left of a column to select the entire column, or drag the cell to the left of the column up or down to rearrange columns. Right-click in the cell to the left of a column to access the column's context menu (for example, to delete a column or display the Properties window). • Properties window—Use this window to edit the name and schema of the table. • Table Designer menu—Use this menu to perform editing tasks such as adding and deleting columns, setting the primary key column, editing indexes and primary keys, editing foreign key relationships, or editing check constraints. The sections that follow describe these tasks in more detail. 7. Select File > Save Tablen or File > Save All to save your changes. 8. When creating a new table, SQLFire.NET Designer prompts you to enter a table name. Specify the schema and table name, separated by a period (for example, APP.Table1). 154 vFabric SQLFire User's Guide Chapter 23 Understanding the Data Consistency Model All peers in a single distributed system are assumed to be colocated in the same data center and accessible with reliable bandwidth and low latencies. Replication of table data in the distributed system is always eager and synchronous in nature. You support synchronous replication by configuring bidirectional WAN gateway senders between two or more distributed systems. Data Consistency Concepts Without a transaction (transaction isolation set to NONE), SQLFire ensures FIFO consistency for table updates. Writes performed by a single thread are seen by all other processes in the order in which they were issued, but writes from different processes may be seen in a different order by other processes. When a table is partitioned across members of the distributed system, SQLFire uniformly distributes the data set across members that host the table so that no single member becomes a bottleneck for scalability. SQLFire ensures that a single member owns a particular row (identified by a primary key) at any given time. When an owning member fails, the ownership of the row is transferred to an alternate member in a consistent manner so that all peer servers have a consistent view of the new owner. It is the responsibility of the owning member to propagate row changes to configured replicas. All concurrent operations on the same row are serialized through the owning member before the operations are applied to replicas. All replicas see the row updates in the exact same order. Essentially, for partitioned tables SQLFire ensures that all concurrent modifications to a row are atomic and isolated from each other, and that the 'total ordering' is preserved across configured replicas. The operations are propagated in parallel from the owning member to all configured replicas. Each replica is responsible for processing the operation, and it responds with an acknowledgment (ACK). Only after receiving all ACKs from all replicas does the owning member return control to the caller. This ensures that all operations that are sequentially carried out by a single process are applied to all replicas in the same order. There are several other optimistic and eventually consistent replication schemes that use lazy replication techniques designed to conserve bandwidth, and increase throughput through batching and lazily forwarding messages. Conflicts are discovered after they happen and reaching agreement on the final contents incrementally. This class of systems favor availability of the system even in the presence of network partitions but compromises consistency on reads or make the reads very expensive by reading from each replica. SQLFire instead uses an eager replication model between peers by propagating to each replica in parallel and synchronously. This approach favors data availability and low latency for propagating data changes. By eagerly propagating to each of its replicas, it is possible for clients reading data to be load balanced to any of the replicas. It is assumed that network partitions are rare in practice and when they do occur within a clustered environment, 155 Developing Applications with SQLFire the application ecosystem is typically dealing with many distributed processes and applications, most of which are not designed to cope with partitioning problems. By offering a very loosely coupled WAN replication scheme, SQLFire enables the entire client load to be shifted to an alternate "disaster recovery" site. No Ordering Guarantee for DML in Separate Threads SQLFire preserves the order of DML statements applied to the distributed system (and queued to AsyncEventlisteners or remote WAN sites) only for a single thread of execution. Updates from multiple threads are preserved in first-in, first-out (FIFO) order. Otherwise, SQLFire provides no "total ordering" guarantees. Data inconsistency can occur if multiple threads concurrently update the same rows of a replicated table, or if threads concurrently update related rows from replicated tables in a parent-child relationship. Concurrently updating the same row in a replicated table can result in some replicas having different values from other replicas. Concurrently deleting a row in a parent table and inserting a row in a child table can result in orphaned rows. When DML operations are queued to an AsyncEventListener or remote WAN site, similar inconsistency problems can occur with concurrent table access. For example, if two separate threads concurrently update rows on a parent table and child table, respectively, the order in which SQLFire queues those updates to an AsyncEventListener or WAN gateway may not match the order in which the tables were updated in the main distributed system. This can cause a foreign key constraint violation in a backend database (for example, when using DBSynchronizer) or in a remote WAN system that does not occur when the tables are initially updated. These types of "out of order" updates do not occur when multiple threads concurrently update the same key of a partitioned table. However, an application should always use a transaction for any operation that updates multiple rows. Updates on Any Row Are Atomic and Isolated When rows are updated members may receive a partial row. SQLFire always clones the existing row, applies the update (changes one or more fields) and then atomically replaces the row with the updated row. This ensures that all concurrent threads reading or writing that row are always guaranteed to be isolated from access to any partial row updates. Atomicity for Bulk Updates SQLFire does not validate all constraints for all affected rows before applying a bulk update (a single DML statement that updates or inserts multiple rows). The design is optimized for applications where such violations are rare. A constraint violation exception that is thrown during a bulk update operation does not indicate which row of the bulk update caused a violation. Applications that receive such an exception cannot determine whether any rows in the bulk operation updated successfully. To address the possibility of constraint violations, an application should apply the bulk update within the scope of a transaction, which ensures that all rows are updated or rolled back as a unit. As an alternative, the application should select rows for updating based on primary keys, and apply updates one at a time. 156 vFabric SQLFire User's Guide Chapter 24 Using Distributed Transactions in Your Applications A transaction is a set of one or more SQL statements that make up a logical unit of work that you can commit or roll back, and that will be recovered in the event of a system failure. SQLFire's unique design for distributed transactions allows for linear scaling without compromising atomicity, consistency, isolation, and durability (ACID) properties. Overview of SQLFire Distributed Transactions All statements in a transaction are atomic. A transaction is associated with a single connection (and database) and cannot span connections. In addition to providing linear scaling, the SQLFire transaction design minimizes messaging requirements, so that short-lived transactions are efficient. • Main Features of the SQLFire Transaction Model on page 157 • How the Transaction Model Works on page 157 Main Features of the SQLFire Transaction Model The SQLFire transaction model uses these important features: • Each SQLFire member that participates in a transaction maintains its own transaction state. Queries on the database always see committed data, and they do not need to acquire any locks; as a result, reads and writes can occur in parallel in the READ_COMMITTED isolation level. • During transactional writes, SQLFire individually locks each copy of a row that is being updated on each member. This alleviates the need for a distributed lock manager, and it allows for greater scalability. Also, SQLFire uses special read locks for REPEATABLE_READ and foreign key checks to ensure that those rows do not change for the duration of a transaction. • SQLFire locks generally fail eagerly (fail-fast) with a conflict exception (SQLState: "X0Z02") if a lock cannot be obtained due to concurrent writes from other active transactions. An exception to this fail-fast behavior occurs when the SQLFire member that initiates the transaction also hosts data for the transaction. In this case, SQLFire batches the transaction on the local member for performance reasons, and conflicts may not be detected on other nodes until just before commit time when SQLFire flushes the batched data. SQLFire never batches operations for SELECT ... FOR UPDATE statements. How the Transaction Model Works When data is managed in partitioned tables, each row is implicitly owned by a single member for non-transactional operations. However, with distributed transactions, all copies of a row are treated as being equivalent, and updates are routed to all copies in parallel. This makes the transactional behavior for partitioned tables similar to the 157 Developing Applications with SQLFire behavior for replicated tables. The transaction manager works closely with the SQLFire membership management system to make sure that, irrespective of failures or adding/removing members, changes to all rows are either applied to all available copies at commit time, or they are applied to none. Note: SQLFire does not support adding new members to a cluster for an ongoing transaction. If you add a new member to the cluster in the middle of a transaction and the new member is to store data involved in the transaction, SQLFire implicitly rolls back the transaction and throws a SQLException (SQLState: "X0Z05"). There is no centralized transaction coordinator in SQLFire. Instead, the member on which a transaction was started acts as the coordinator for the duration of the transaction. If the application updates one or more rows, the transaction coordinator determines which owning members are involved, and acquires local "write" locks on all of the copies of the rows. At commit time, all changes are applied to the local cache and any redundant copies. If another concurrent transaction attempts to change one of the rows, the local "write" acquisition fails for the row, and that transaction is automatically rolled back. In the case where there is no persistent table involved, there is no need to issue a two-phase commit to redundant members; in this case, commits are efficient, single-phase operations. Unlike traditional distributed databases, SQLFire does not use write-ahead logging for transaction recovery in case the commit fails during replication or redundant updates to one or more members. The most likely failure scenario is one where the member is unhealthy and gets forced out of the distributed system, guaranteeing the consistency of the data. When the failed member comes back online, it automatically recovers the replicated/redundant data set and establishes coherency with the other members. If all copies of some data go down before the commit is issued, then this condition is detected using the group membership system, and the transaction is rolled back automatically on all members. Supported Transaction Isolation Levels SQLFire supports several transaction isolation levels. It does not support the SERIALIZABLE isolation level, nested transactions, or savepoints. SQLFire supports these transaction isolation levels: • NONE. By default, connections in SQLFire do not engage in transactions, unlike in other databases (see Data Consistency Concepts on page 155. This corresponds to the JDBC TRANSACTION_NONE isolation level (or IsolationLevel.Chaos in ADO.NET, or the "SET ISOLATION RESET" SQL command). However, this default behavior does not mean that there is no isolation and that connections have access to uncommitted state from other in-process transactions. The default consistency model without transactions is described in Understanding the Data Consistency Model on page 155. • READ_UNCOMMITTED. SQLFire internally upgrades this isolation to READ_COMMITTED. • READ_COMMITTED. SQLFire ensures that ongoing transactional as well as non-transactional (isolation-level NONE) operations never read uncommitted (dirty) data. SQLFire accomplishes this by maintaining transactional changes in a separate transaction state that is applied to the actual data-store for the table only at commit time. • REPEATABLE_READ. SQLFire supports the REPEATABLE_READ isolation level according to the ANSI SQL standard. A transaction that reads the same row more than once always sees the same column values for the row. REPEATABLE_READ also guarantees that the underlying committed row in a table never changes after the first read in a transaction, until the transaction completes (for example, it commits or aborts). SQLFire applies read and write locks to copies of selected data to ensure repeatable reads for the duration of a transaction. SQLFire does not use range locks, and phantom reads are still possible with this isolation level. In addition, readers that use the REPEATABLE_READ isolation level are guaranteed to see distributed, atomic commits. This means that if there is a transaction that writes rows and commits over multiple SQLFire members, then readers either see all of the commit row values across all members of the distributed system (after the commit), or they will see all of before-committed row values across all members. Readers never see some committed rows on one member and before-committed row values on another node. To support this behavior, SQLFire uses a 2-phase commit protocol for all REPEATABLE_READ transactions that have pending writes. 158 vFabric SQLFire User's Guide Using Distributed Transactions in Your Applications SQLFire detects conflicts between two transactions that write on the same row either during the transactions or just before a commit for READ_COMMITTED and REPEATABLE_READ transactions. However, if a REPEATABLE_READ transaction writes on the same row that has been read by another transaction, then SQLFire always detects such a conflict before the writer commits (in the first phase of the commit). This enables the system to minimize conflicts where reader transactions are short in duration and the transactions complete before the writer starts its commit. Note: REPEATABLE_READ transactions that have only performed reads never receive a conflict. In particular, even if a transaction reads a row after it has already been marked for write by another transaction, it is the writer that sees the conflict at commit time if the reader transaction has not completed by then. For both the write-write and write-read cases, if a reader or writer attempts to lock a row while the commit of another writer transaction on the row is in progress, then the reader waits for the commit to complete. The commit is usually short in duration, so this behavior reduces conflicts and ensures that the wait is finite. SQLFire provides these system properties that you can use to alter the conflict detection behavior for READ_COMMITTED and REPEATABLE_READ transactions: gemfire.WRITE_LOCK_TIMEOUT, gemfire.READ_LOCK_TIMEOUT, and gemfire.LOCK_MAX_TIMEOUT. Note: You must set these system properties to the same value on each data store in your SQLFire distributed system. For more information, see: • SET ISOLATION on page 543 • java.sql.Connection Interface on page 365 • sqlf commands: autocommit on page 451, commit on page 453, and rollback on page 469. Transactions and DDL Statements SQLFire permits schema and data manipulation statements (DML) within a single transaction. If you create a table in one transaction, you can also insert data into it in that same transaction. A schema manipulation statement (DDL) is not automatically committed when it is performed, but participates in the transaction within which it is issued. Although the table itself becomes visible in the system immediately, it acquires exclusive locks on the system tables and the affected tables on all the members in the cluster, so that any DML operations in other transactions will block and wait for the table's locks. For example, if a new index is created on a table in a transaction, then all other transactions that refer to that table wait for the transaction to commit or roll back. Because of this behavior, as a best practice you should keep transactions that involve DDL statements short (preferably in a single transaction by itself). Handling Member Failures These events occur in response to the failure of a single member during a transaction. 1. If the coordinator fails before a commit is fired, then each of the cohorts aborts the ongoing transaction. 2. If a participating member fails before commit is fired, then it is simply ignored. If the copies/replicas go to zero for certain keys, then any subsequent update operations on those keys throws an exception as in the case of non-transactional updates. If a commit is fired in this state, then the whole transaction is aborted. 3. If the coordinator fails before completing the commit process (with or without sending the commit message to all cohorts), the surviving cohorts determine the outcome of the transaction. If all of the cohorts are in the PREPARED state and successfully apply changes to the cache without any unique constraint violations, the transaction is committed on all cohorts. Otherwise, if any member reports 159 Developing Applications with SQLFire failure or the last copy the associated rows goes down during the PREPARED state, the transaction is rolled back on all cohorts. 4. If a participating member fails before acknowledging to the client, then the transaction continues on other members without any interruption. However, if that member contains the last copy of a table or bucket, then the transaction is rolled back. Note: In this release of SQLFire, a transaction fails if any of the cohorts depart abnormally. Sequence of Events for a Distributed Transaction Here is a step-by-step description of events that occur before and during the transaction commit sequence. Before a transaction is committed, the following events occur: 1. When a transaction is started the transaction coordinator creates a globally unique ID (TXID) and creates a work space (TXState) to track operations. If the transaction is started from a thin client connection, the coordination happens on the server to which the client is connected. Note that transactions are started implicitly in JDBC: the end of one transaction implicitly starts a new one. 2. All updates in the scope of a transaction are immediately propagated to all replicas in parallel and are partially coordinated on each data store (cohort). Each member that owns the data involved in the transaction manages the state in a local TXState. When updates are received by a cohort, it attempts to obtain local write locks on the rows. A cohort fails immediately if the rows are already locked by another transaction. Failure to obtain locks results in the coordinator implicitly rolling back the entire transaction and releasing all the locks on the data hosts. 3. SQLFire only detects Write-Write conflicts. To prevent rows fetched in the transaction from being modified before transaction commit, SQLFire supports select for update where the selected rows are locked before the result set can be returned. 4. While the transaction is in progress the updates are maintained only in the TXState on the data stores, completely isolated from other concurrent connections. 5. Any constraint checks on the rows are immediately applied, and failures result in a constraint violation exception. Note: In this release of SQLFire, constraint violations also implicitly roll back the transaction. 6. Readers do not normally acquire any locks unless the rows being read are about to be committed. Transactional read operations are applied to the TXState first, before they are applied to the committed state. 7. When using the REPEATABLE_READ isolation level, all rows from selects are written first to the TXSTate before they are returned to the application. These events occur during the transaction commit sequence: 1. When a commit message is received by the coordinator, it dispatches a single commit message to all of the cohorts. Because the rows are already locked and constraints applied during the transaction, it is certain that the transaction will not fail due to conflicts. 2. Each cohort guarantees transaction atomicity by making sure that no concurrent transaction can see partially-committed state on the data store. Note that even though SQLFire guarantees that no concurrent access sees the partially-committed state of a transaction on any single cohort, the commit phase does not guarantee that to be the case across all of the cohorts that are involved in the transaction. 3. Each cohort applies the TXState changes to the tables in memory, and releases all the locks before acknowledging to the coordinator. 160 vFabric SQLFire User's Guide Using Distributed Transactions in Your Applications Note: Because the outcome of the transaction is assured at commit time, the coordinator does not wait for individual commit replies from the cohorts before returning the committed transaction to the initiating thread. If the same connection immediately initiates another operation on the same data, then the cohorts wait for pending replies from the previous transaction (as described in Step 3) before applying the change. Also, a commit or rollback operation takes place even if the initiating client process becomes unavailable while the commit or rollback is performed. SQLFire Transaction Design SQLFire implements optimistic transactions. The transaction model is highly optimized for colocated data, where all of the rows updated by a transaction are owned by a single member. SQLFire avoids the use of a centralized distributed lock manager and the traditional 2-phase commit protocol. Transactional state is managed on each data store that is affected by the transaction, using only local locks. This allows the cluster to scale even when applications utilize transactions. When 2-phase commit is used, SQLFire performs second-phase commit actions in the background, but ensures that the connection that initiated the transaction sees only the committed results. You can change this default behavior using the sync-commits property. SQLFire uses an "eager lock, fail fast" algorithm that capitalizes on the fact that updates are reliably and synchronously propagated to all cohorts (mainly replicas). The main ideas behind this algorithm are summarized as follows: • Acquire eager locks. Each transactional write operation is synchronously propagated to each replica where a local transaction coordinator acquires a LOCAL write lock on the key. • Fail fast. If the write lock cannot be acquired, presumably due to a concurrent, conflicting transaction, then the write backs off and marks the transaction for rollback. The transaction outcome cannot be reversed. • Transaction state. All the changes in a transaction are maintained on every member affected by the transaction (every member that hosts a copy of a row changed in the transaction) in a transaction state. The changes are applied locally to the underlying table data only on commit. This allows readers to execute concurrently with a single writer without requiring any locks or blocking in the READ_COMMITTED isolation level. The focus for this design is on "optimistic transactions" and the design makes these important assumptions: • The typical transaction duration is short. • Conflicts between transactions are rare. If concurrent transactions tend to conflict, it is the application's responsibility to retry the failed transaction. Using this design provides the potential for linear scaling. Without centralized lock management, transaction throughput can easily scale with additional members. Transaction processing involves the data stores plus a coordinating peer. Thus if the concurrent transaction workload is uniformly spread across the data set, increasing the number of data stores also balances the workload and increases the aggregate transaction throughput. The design also removes the colocation restriction for the transactional working set, because transactions can involve any number of data hosts. Transaction performance is also increased, as compared to transactions that use a centralized lock manager. Best Practices for Using Transactions For optimum results, take note of best practices for working with SQLFire transactions. • For high performance, mimimize the duration of transactions to avoid conflicts with other concurrent transactions. If atomicity for only single row updates is required, then completely avoid using transactions because SQLFire provides atomicity and isolation for single rows without transactions. 161 Developing Applications with SQLFire • Unlike in traditional databases, SQLFire transactions can fail with a conflict exception on updates instead of on commit. This choice makes sense given that the outcome of the transaction has been determined to fail. • When using transactions, keep the transaction duration and the number of rows involved in the transaction as low as possible. SQLFire acquires locks eagerly, and long-lasting transactions increase the probability of conflicts and transaction failures. • To the extent possible, model your database so that most transactions operate on colocated data. When all transactional data is on a single member, then stricter isolation guarantees are provided. • If your application spawns multiple threads or connections to work on committed data, consider setting the sync-commits conenction property to "true." By default SQLFire performs second-phase commit actions in the background, but ensures that the connection that issued the transaction only sees completed results. However, other threads or connections may see different results until the second-phase commit actions complete. setting sync-commits=true ensures that the current thin client or peer client connection waits until all second-phase commit actions complete. Transaction Functionality and Limitations Take note of transaction behavior and limitations in this release of SQLFire. In this release of SQLFire, the scope for transactional functionality is: • The result set that is obtained from executing a query should either be completely consumed, or the result set is explicitly closed. Otherwise, DDL operations wait until the ResultSet is garbage-collected. • Transactions for persistent tables are enabled by default, but the full range of fault tolerance is not yet implemented. It is assumed that at least one copy of a row is always available (redundant members are available) in the event of member failures. • SQL statements that implicitly place locks, such as select for update, are not supported outside of transactions (default isolation level). • The supported isolation levels are 'READ COMMITTED' and 'READ UNCOMMITTED' where both behave as 'READ COMMITTED.' Autocommit is OFF by default in SQLFire, unlike in other JDBC drivers. • Transactions always do "write-write" conflict detection at operation or commit time. Applications do not need to use select for update or explicit locking to get this behavior, as compared to other databases. (select for update is not supported outside of a transaction.) • Nested transactions and savepoints are not supported. • SQLFire does not restrict concurrent non-transactional clients from updating tables that may be involved in transactions. This is by design, to maintain very high performance when no transactions are in use. If an application uses transactions on a table, make sure the application consistently uses transactions when updating that table. • All DML on a single row is atomic in nature inside or outside of transactions. • There is a small window during a commit when the committed set is being applied to the underlying table and concurrent readers, which do not consult any transactional state, have visibility to the partially-committed state. The larger the transaction, the larger the window. Also, transaction state is maintained in a memory-based buffer. The shorter and smaller the transaction, the less likely the transaction manager will run short on memory. 162 vFabric SQLFire User's Guide Chapter 25 Using Data-Aware Stored Procedures A stored procedure is an application function call or subroutine that is managed in the database server. Because multiple SQLFire members operate together in a distributed system, procedure execution in SQLFire can also be parallelized to run on multiple members, concurrently. A procedure that executes concurrently on multiple SQLFire members is called a data-aware procedure. Data-aware procedures use an extended CALL syntax with an ON clause to designate the SQLFire members on which the procedure executes. When you invoke a procedure, the SQLFire syntax provides the option to parallelize the procedure execution on: • All data stores in the SQLFire cluster • A subset of data stores (on members that belong to one or more server groups) • All data store members that host a table • All data store members that host a subset of data in a table SQLFire executes the user code in-process to where the data resides, which provides very low-latency access to colocated data. (This is in contrast to map-reduce job execution frameworks like Hadoop, where data has to be streamed from processes into a Task process.) Procedures often return one or more result sets. SQLFire streams a result set to one coordinating member that can perform the reduction step on the results (typically this involves aggregation, as in map-reduce). In SQLFire, the reduction step is carried out by a result processor. SQLFire provides a default result processor, and you can also develop your own result processor implementations to customize the reduction step. The sections that follow describe how to configure, invoke, and develop stored procedure and result processor implementations in SQLFire. Configuring a Procedure You must configure a procedure implementation in SQLFire before you can invoke the procedure. Before you configure a procedure, ensure that the procedure implemention is available in the SQLFire classloader. See Storing and Loading JAR Files in SQLFire on page 131. The syntax for configuring a procedure in SQLFire is as follows. You designate a procedure as data-aware or data-independent when you invoke it. See Invoking a Procedure on page 165. CREATE PROCEDURE procedure-name ([ procedure-parameter [, procedure-parameter] * ]) LANGUAGE JAVA PARAMETER STYLE JAVA { NO SQL | CONTAINS SQL | READS SQL DATA | MODIFIES SQL DATA } 163 Developing Applications with SQLFire [ [DYNAMIC] RESULT SETS integer] EXTERNAL NAME 'procedure_external_class.method' The procedure-name is a SQL identifier that you can use to call the procedure implementation in SQLFire. The procedure_external_name specifies the actual static class_name.method_name of the Java procedure implementation. Using the Procedure Provider API on page 169 provides more information about implementing procedures. One or more procedure-parameter entries use the syntax: [ { IN | OUT | INOUT } ] [parameter_name] DataType Each parameter entry should match a corresponding parameter in the procedure's Java implementation. SQLFire supports the data types described in Data Types on page 638, including user-defined types (see Programming User-Defined Types on page 177). The results of a procedure, if any, can be supplied as OUT parameters, INOUT parameters, or as dynamic result sets. A client retrieves OUT parameters using methods in java.sql.CallableStatement. The NO SQL, CONTAINS SQL, READS SQL DATA, and MODIFIES SQL DATA options are used to describe the type of SQL statements that the procedure uses. Choose one of the available options: • NO SQL indicates that the stored procedure does not execute any SQL statements. • CONTAINS SQL indicates that the procedure does not execute SQL statements that read nor modify SQL data. • READS SQL DATA indicates that the procedure does not execute SQL statements that modify SQL data, but may issue other statements (such as SELECT statements) to read data. • MODIFIES SQL DATA indicates that the procedure can execute any SQL statement except those that are specifically disallowed in stored procedures. SQLFire uses MODIFIES SQL DATA as the default. SQLFire throws an exception if a procedure attempts to execute SQL statements that conflict with the NO SQL, CONTAINS SQL, or MODIFIES SQL DATA setting. RESULT SETS indicates the estimated upper bound of returned result sets for the procedure. Access result sets by calling the getMoreResults() and getResultSet() statements in java.sql.Statement. EXTERNAL NAME specifies the fully qualified class name and method name of the procedure to create. Example CREATE PROCEDURE SALES.TOTAL_REVENUE(IN S_MONTH INTEGER, IN S_YEAR INTEGER, OUT TOTAL DECIMAL(10,2)) LANGUAGE JAVA PARAMETER STYLE JAVA READS SQL DATA EXTERNAL NAME 'com.sqlfire.funcs.Revenue.calculateRevenueByMonth' Configuring a Custom Result Processor Data-aware procedures use a separate result processor to merge the procedure results from multiple SQLFire members. You can use the default SQLFire result processor, or implement and configure your own result processor implementation to customize the merge behavior. Using the Procedure Provider API on page 169 describes how to implement a custom result processor. 164 vFabric SQLFire User's Guide Using Data-Aware Stored Procedures Note: When working with custom result processors, you may find it helpful to create an alias for the result processor class name. You can use the alias in place of the full result processor class name when you invoke a data-aware procedure. To create an alias use the SQL statement: CREATE ALIAS processor_alias FOR 'processor_class_name' where processor_class_name is the full name of a class that implements com.vmware.sqlfire.ProcedureResultProcessor and has a default constructor. Invoking a Procedure SQLFire uses an extended CALL syntax for invoking data-aware procedures. The SQLFire syntax for invoking a procedure is: CALL procedure_name ( [ expression [, expression ]* ] ) [ WITH RESULT PROCESSOR processor_class ] [ { ON TABLE table_name [ WHERE whereClause ] } | { ON { ALL | SERVER GROUPS (server_group_name [, server_group_name]* ) } } ] Use the optional ON and WHERE clauses to provide routing hints to the SQLFire engine, in order to prune the procedure execution to a subset of SQLFire members: • ON TABLE executes the procedure code on SQLFire members that host data for the table. With partitioned tables, you can also use the WHERE clause to further specify only those members host specific data values for the table. Note that both the ON TABLE and WHERE clauses are only used to prune procedure execution to specific members; the clauses do not limit the data results, and neither the ON TABLE nor the WHERE clause restriction is applied to queries within the procedure body. • ON ALL executes the procedure code on all SQLFire members, while ON SERVER GROUPS executes the procedure code on one or more named server groups. Note: Specifying ON TABLE, ON ALL, and ON SERVER groups also affects the scoping of nested queries within the procedure implementation. See Populating Result Sets on page 170 and Using the and Escape Syntax with Nested Queries on page 172 for more information. If you omit the ON clause, SQLFire executes the procedure as a data-independent procedure on the local, coordinating member. If you omit the WITH RESULT PROCESSOR clause when calling a data-aware procedure, then SQLFire uses a default result processor implementation. If the called procedure does not specify an OUT parameter or result set, then SQLFire calls the procedure asynchronously, without waiting for a reply. SQLFire logs any error that occurs during procedure execution. High Availability for SQLFire Procedures If an error occurs before a procedure has returned any rows to the client, then SQLFire automatically re-executes the procedure. Procedure and result processor implementations can use the isPossibleDuplicate() method to determine if SQLFire re-executed a procedure after a SQLFire member failed. This type of detection is necesary for certain implementations that perform write operations that can lead to duplicate entries on procedure re-execution. 165 Developing Applications with SQLFire If an error occurs after rows have been returned to the client, then SQLFire throws an exception and does not attempt to retry the procedure. Default Result Processor If you omit the WITH RESULT PROCESSOR clause when you invoke a data-aware procedure, SQLFire uses a default result processor implementation. The default result processor for data-aware procedures performs unordered merges on the dynamic result sets from each member that executes the procedure code. The default processor presents the same number of ResultSets to the JDBC client that were declared in the CREATE PROCEDURE statement. The default processor handles OUT and INOUT parameters as follows: • If the type is a basic SQL type, the default processor returns only the first value returned by the procedure. • If the type is a JAVA_OBJECT type, the values from all the servers that run the procedure are concatenated together as an object array and provided to the client as the object value. The ordering of the array elements is significant because a given array position corresponds to the same SQLFire member for each of the parameters. For example, the first element of each array corresponds to the OUT parameters that were provided by the same SQLFire member. Example JDBC Client This example shows how a JDBC client can call a data-aware procedure and use a CallableStatement to work with the procedure's result sets. package com.vmware.sqlfire.jdbc; import import import import import import import import java.io.Serializable; java.sql.CallableStatement; java.sql.Connection; java.sql.DriverManager; java.sql.ResultSet; java.sql.SQLException; java.sql.Statement; java.sql.Types; import com.vmware.sqlfire.procedure.ProcedureExecutionContext; public class MyClient { public static class ExampleObj implements Serializable { private static final long serialVersionUID = 1L; private int val; public void setValue(int val) { this. val = val; } public int getValue() { return this.val; } } public static void main(String[] args) { try { Connection cxn = DriverManager.getConnection("jdbc:sqlfire:"); Statement stmt = cxn.createStatement(); stmt.execute("create type ExampleObjType external name '" 166 vFabric SQLFire User's Guide Using Data-Aware Stored Procedures + ExampleObj.class.getName() + "' language java"); stmt.execute("CREATE PROCEDURE myProc " + "(IN inParam1 VARCHAR(10), " + + + + + " OUT outParam2 INTEGER, " " INOUT example ExampleObjType, OUT count INTEGER)" "LANGUAGE JAVA PARAMETER STYLE JAVA " + "READS SQL DATA " "DYNAMIC RESULT SETS 2 " + "EXTERNAL NAME '" ProcedureTest.class.getName() + ".myProc'"); stmt.execute("create table MyTable(x int not null, y int not null)"); stmt.execute("insert into MyTable values (1, 10), (2, 20), (3, 30), (4, 40)"); CallableStatement callableStmt = cxn .prepareCall("{CALL myProc('abc', ?, ?, ?) ON TABLE MyTable WHERE x BETWEEN 5 AND 10}"); callableStmt.registerOutParameter(1, Types.INTEGER); callableStmt.registerOutParameter(2, Types.JAVA_OBJECT); callableStmt.registerOutParameter(3, Types.INTEGER); callableStmt.setObject(2, new ExampleObj()); callableStmt.execute(); int outParam2 = callableStmt.getInt(1); ExampleObj example = (ExampleObj)callableStmt.getObject(2); assert example.getValue() == 100; assert outParam2 == 200; ResultSet thisResultSet; boolean moreResults = true; int cnt = 0; int rowCount = 0; do { thisResultSet = callableStmt.getResultSet(); int colCnt = thisResultSet.getMetaData().getColumnCount(); if (cnt == 0) { System.out.println("Result Set 1 starts"); while (thisResultSet.next()) { for (int i = 1; i < colCnt + 1; i++) { System.out.print(thisResultSet.getObject(i)); if (i == 1) { System.out.print(','); } } System.out.println(); rowCount++; } System.out.println("ResultSet 1 ends\n"); cnt++; } else { thisResultSet.next(); System.out.println("ResultSet 2 starts"); for (int i = 1; i < colCnt + 1; i++) { cnt = thisResultSet.getInt(1); System.out.print(cnt); System.out.println(); } 167 Developing Applications with SQLFire System.out.println("ResultSet 2 ends"); } moreResults = callableStmt.getMoreResults(); } while (moreResults); assert rowCount == cnt; assert rowCount == 4; } catch (SQLException e) { e.printStackTrace(); } } public static void myProc(String inParam1, int[] outParam2, ExampleObj[] example, int[] count, ResultSet[] resultSet1, ResultSet[] resultSet2, ProcedureExecutionContext ctx) throws SQLException { Connection conn = ctx.getConnection(); ExampleObj obj = new ExampleObj(); obj.setValue(100); example[0] = obj; outParam2[0] = 200; Statement stmt = conn.createStatement(); stmt.execute("select * from mytable"); resultSet1[0] = stmt.getResultSet(); Statement stmt3 = conn.createStatement(); stmt3 .execute("select count(*) from mytable"); stmt3.getResultSet().next(); Integer cnt = stmt3.getResultSet().getInt(1); count[0] = cnt; Statement stmt2 = conn.createStatement(); stmt2.execute("select count(*) from mytable"); resultSet2[0] = stmt2.getResultSet(); } } 168 vFabric SQLFire User's Guide Chapter 26 Using the Procedure Provider API SQLFire provides an API to help you develop data-aware procedures. A ProcedureExecutionContext object provides information about the table used to filter the procedure execution, colocated data, and other information about the context in which a procedure is executed. An OutgoingResultSet interface enables you to construct a result set by adding rows or columns to a List object. Use the information in this section to develop and compile your procedure, and then add the implementation to SQLFire using the instructions in Storing and Loading JAR Files in SQLFire on page 131. You can then configure and execute the procedure using the information in Using Data-Aware Stored Procedures on page 163. Procedure Parameters When you configure a procedure using the CREATE PROCEDURE statement, SQLFire assembles the method parameters and passes them to the procedure implementation class using Java reflection. The different types of parameters are handled in the following ways: • IN and INOUT parameters are passed to the procedure implementation as single-element arrays. • DYNAMIC RESULT SETS specified in the CREATE PROCEDURE statement cause additional method arguments to be appended, one for each dynamic result set. Each argument is treated as a ResultSet[] type. SQLFire passes in each argument as a single-element array containing a null value. For example, if you specify DYNAMIC RESULT SETS 2, SQLFire appends two additional ResultSet[] arguments, each with a single null value. ResultSets are returned to the application through the CallableStatement, in the order that they are defined in the procedure body. See Populating Result Sets on page 170. • The procedure implementation class can optionally specify a ProcedureExecutionContext parameter as the last parameter. SQLFire then passes in the procedure context object, which the implementation can use to determine information about the execution context. Note: The CREATE PROCEDURE and CALL statements should not reference the procedure context object as a procedure parameter. For example, if the Java method signature of the procedure implementation is: package com.acme.MyProc; import java.sql.*; public class MyProc {public static void myMethod(String inParam1, Integer[] outParam2, Date[] inoutParam3, 169 Developing Applications with SQLFire Widget[] inoutParam4, ResultSet[] resultSet1, ResultSet[] resultSet2) { ... } } You would configure the procedure in SQLFire using a statement similar to: CREATE PROCEDURE myProc (IN inParam1 VARCHAR(10), OUT outParam2 INTEGER, INOUT DATE inoutParam3, INOUT WidgetType inoutParam4) LANGUAGE JAVA PARAMETER STYLE JAVA READS SQL DATA DYNAMIC RESULT SETS 2 EXTERNAL NAME 'com.acme.MyProc.myMethod' Note: The formal parameter names are used as an example, and the actual parameter names need not match. Note: A user-defined type (WidgetType) implementation would have to be created elsewhere in this example. This same CREATE PROCEDURE statement could be used even if the Java implementation included a ProcedureExecutionContext in the method signature, as in the following example. package com.acme.MyProc; import java.sql.*; public class MyProc {public static void myMethod(String inParam1, Integer[] outParam2, Date[] inoutParam3, Widget[] inoutParam4, ResultSet[] resultSet1, ResultSet[] resultSet2, ProcedureExecutionContext context) { ... } } Populating OUT and INOUT Parameters Your procedure implementation returns OUT and INOUT parameters if you set their values in the single-element array. For example, the following code sets an OUT and an INOUT parameter: outParam2[0] = 42; inoutParam3[0] = new java.sql.Date(System.currentTimeMillis()); Populating Result Sets The SQLFire API provides different ways to construct result sets in a procedure implementation. 170 vFabric SQLFire User's Guide Using the Procedure Provider API A procedure must open and generate a ResultSet either from the default connection (jdbc:default:connection) or from the connection that is obtained from the ProcedureExecutionContext object. SQLFire ignores result sets that are generated in any other manner. If your implementation requires a result set from a thin client connection or from a connection to an external database, then create an OutgoingResultSet to populate the results from the connection. See Using Result Sets and Cursors on page 181 for more information about using result sets in SQLFire. SQLFire returns ResultSets to the application through the CallableStatement, in the order that they are defined in the procedure body. Your procedure implementation can return fewer ResultSets than are defined in the DYNAMIC RESULT SETS clause; construct only those ResultSets that you require. Create all PreparedStatement or other Statement objects directly in the body of the procedure method that requires those objects. Do not attempt to cache statement objects as static variables. In contrast to a JDBC client application method, a Java procedure method cannot hold onto a JDBC object after it completes. Also, do not close a statement that generates a ResultSet, because doing so closes the ResultSet itself. The SQLFire API provides two ways to help you construct a result sets in the procedure implementation: • Execute a Query to Populate a Result Set on page 171 • Construct a Result Set with OutgoingResultSet on page 171 Execute a Query to Populate a Result Set The ProcedureExecutionContext provides a getConnection() method that returns a nested JDBC connection. You use this connection (or the default connection) to populate one or more ResultSets with a nested query. Data for the nested query is not manifested until next() is called on the ResultSet. SQLFire calls next() on the ResultSets as necessary to stream the required rows. For example: Connection cxn = context.getConnection(); Statement stmt = cxn.createStatement(); resultSet1[0] = stmt.executeQuery("select * from Bar where foo > 42"); resultSet2[0] = stmt.executeQuery("select * from Bar where foo <= 42"); SQLFire creates the one-element ResultSet arrays that hold the returned ResultSets. Note: Do not close the connection or the statement that you use to create the result set, because doing so also closes the result set. Remember that a data-aware procedure might be invoked with a WHERE clause that restricts execution to one or more SQLFire members, and the procedure implementation itself might execute a nested query on the same table. By default, nested queries execute only on those SQLFire members that were scoped at procedure invocation. Using the and Escape Syntax with Nested Queries on page 172 describes how to override the default scope for nested queries when required by your procedure implementation. Construct a Result Set with OutgoingResultSet As an alternative, the procedure can obtain an empty OutgoingResultSet object from the ProcedureExecutionContext or default connection, and then invoke addColumn() for each column of the result set followed by addRow() for each row. You can skip the initial calls to addColumn() if you want to use default column names, such as "c1," "c2," and so forth. When you use this method to construct a result set, SQLFire can immediately stream results after a call to addRow(), even while the procedure implementation continues to add rows. 171 Developing Applications with SQLFire For example: OutgoingResultSet rs1 = context.getOutgoingResultSet(1); rs1.addColumn("field1"); rs1.addColumn("field2"); for (int i = 0; i < 10; i++) { rs1.addRow(new Object[i, String.valueOf(i)]); } rs1.endResults(); Note: Do not close the connection or the statement that you use to create the result set, because doing so also closes the result set. Using the and Escape Syntax with Nested Queries A query that is nested within a data-aware procedure may be executed on local member data, or it may be re-distributed to the SQLFire cluster and executed on multiple SQLFire members. The and escape syntax can be used to override the default behavior for nested queries. If a data-aware procedure is invoked without specifying a WHERE clause in the CALL statement, then by default SQLFire treats a nested query in the procedure implementation as a "global" query. This means that the nested query is distributed to the SQLFire cluster and accesses table data from all SQLFire members that host data for the table. Note that global queries can return duplicate results with a single procedure call, because each member that executes the procedure body invokes a separate global query. If a procedure is invoked using a WHERE clause, then by default SQLFire treats the nested query in the procedure implementation as a "local" query. This means that the query only accesses the local partitioned table data that is assigned to the procedure on the SQLFire member where the procedure executes. You can override this default behavior by specifying either the "" or "" escape syntax at the very beginning of a nested query string in your procedure implementation. For example, the following nested queries always operate with local table data, even you invoke the procedure without specifying a WHERE clause: Connection cxn = context.getConnection(); Statement stmt = cxn.createStatement(); resultSet1[0] = stmt.executeQuery(" select * from Bar where foo > 42"); resultSet2[0] = stmt.executeQuery(" select * from Bar where foo <= 42"); Note: When you use the ON TABLE clause to invoke a procedure, any queries within the procedure body target only the primary data for a partitioned table on the local node. For replicated tables, a local query accesses only a single replica. In both cases, this avoids returning duplicate values in the procedure. When you use ON ALL to invoke a procedure, queries execute only the local member for partitioned table data. However, queries against replicated tables return duplicate results. 172 vFabric SQLFire User's Guide Chapter 27 Using the Custom Result Processor API Data-aware procedures use a separate result processor to merge the procedure results from multiple SQLFire members. You can use the default SQLFire result processor when basic concatenation of the results are required. Default Result Processor on page 166 describes how the default processor works. For more complex use cases, such as sorting, merging, or joining the results from different servers, you must implement your own result processor to customize the merge behavior. A custom processor can be used to modify a procedure's OUT parameters and result sets before emitting the results to a client. The sections that follow describe how to use the SQLFire result processor API to implement your own custom result processor. Sample code is provided for a result processor that performs comparison-based sorting (merge sort) of data-aware procedure results. Implementing the ProcedureResultProcessor Interface A custom result processor must implement the SQLFire ProcedureResultProcessor interface. SQLFire calls the processor implementation after a client invokes a procedure using the WITH RESULT PROCESSOR clause and begins retrieving results. The basic result processor API operates in the following manner: 1. SQLFire calls the init() method of the implementation to provide the ProcedureProcessorContext object. The ProcedureProcessorContext provides important details about the procedure implementation and the procedure call that is returning results to the client. ProcedureProcessorContext describes the methods that you can use to obtain context information and obtain nested JDBC connections. 2. Your implementation uses the ProcedureProcessorContext object to obtain the OUT parameters and result sets that the procedure is returning to the client, so that it can process the results as necessary. OUT parameters and result sets are obtained using the getIncomingOutParameters() and getIncomingResultSets() methods, respectively. Both of these methods returns an IncomingResultSet, which you can use to obtain metadata about the result set itself and inspect individual rows of the result set. 3. SQLFire calls the getNextResultRow() and getOutParameters() methods in your implementation to provide modified results to the client. The getNextResultRow() method of your implementation is called each time the next row of a particular result set must be returned to the client. The getOutParameters() should return all of the procedure's OUT parameters to the client. 4. SQLFire calls your implementation's close() method when the associated statement is closed and the output processor is no longer required. Free resources and perform any final cleanup in this method. Procedure Result Processor Interfaces on page 480 provides a complete reference to the methods defined in ProcedureResultProcessor, ProcedureProcessorContext, and IncomingResultSet. Example Result Processor: MergeSort This example result processor implementation uses a merge sort algorithm to return sorted results to a client. 173 Developing Applications with SQLFire The MergeSort processor is designed for use with a single procedure implementation that returns only a single result set and no OUT parameters. The procedure implementation is shown in Procedure Implementation on page 174, and the procedure would be configured in SQLFire using a statement similar to the following. CREATE PROCEDURE MergeSort () LANGUAGE JAVA PARAMETER STYLE JAVA READS SQL DATA DYNAMIC RESULT SETS 1 EXTERNAL NAME 'examples.MergeSortProcedure.mergeSort' Your own result processor implementations may need to work with the output from multiple procedures, and take into account the possibility of multiple result sets and OUT parameters accordingly. Procedure Implementation The example result processor supports this procedure implementation. The procedure uses a single result set and no OUT parameters. package examples; import com.vmware.sqlfire.*; import java.sql.*; public class MergeSortProcedure { static final String LOCAL = ""; public static void mergeSort(ResultSet[] outResults, ProcedureExecutionContext context) throws SQLException { String queryString = LOCAL + "SELECT * FROM " + context.getTableName(); Connection cxn = context.getConnection(); Statement stmt = cxn.createStatement(); ResultSet rs = stmt.executeQuery(queryString); outResults[0] = rs; // Do not close the connection since this would also // close the result set. } } Merge Sort Result Processor This result processor implementation sorts the results from the MergeSortProcedure, which returns a single result set. package examples; import com.vmware.sqlfire.*; import java.sql.*; import java.util.*; public class MergeSortProcessor implements ProcedureResultProcessor { private ProcedureProcessorContext context; public void init(ProcedureProcessorContext context) { this.context = context; 174 vFabric SQLFire User's Guide Using the Custom Result Processor API } public Object[] getOutParameters() { throw new AssertionError("this procedure has no out parameters"); } public Object[] getNextResultRow(int resultSetNumber) throws InterruptedException { // this procedure deals with only result set number 1 assert resultSetNumber == 1; IncomingResultSet[] inSets = context.getIncomingResultSets(1); Object[] lesserRow = null; Comparator cmp = getComparator(); IncomingResultSet setWithLeastRow = null; for (IncomingResultSet inSet : inSets) { Object[] nextRow = inSet.waitPeekRow(); // blocks until row is available if (nextRow == IncomingResultSet.END_OF_RESULTS) { // no more rows in this incoming results continue; } // find the least row so far if (lesserRow == null || cmp.compare(nextRow, lesserRow) <= 0) { lesserRow = nextRow; setWithLeastRow = inSet; } } if (setWithLeastRow != null) { // consume the lesserRow by removing lesserRow from the incoming result set Object[] takeRow = setWithLeastRow.takeRow(); assert takeRow == lesserRow; } // if lesserRow is null, then there are no more rows in any incoming results return lesserRow; } public boolean getMoreResults(int nextResultSetNumber) { return false; // only one result set } public void close() { this.context = null; } /** Return an appropriate Comparator for sorting the rows */ private Comparator getComparator() { // return an appropriate comparator for the rows throw new UnsupportedOperationException("comparator not implemented"); } } 175 Chapter 28 Programming User-Defined Types SQLFire enables you to create user-defined types. A user-defined type is a serializable Java class whose instances are stored in columns. Note: This topic was adapted from the Apache Derby documentation source, and is subject to the Apache license: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. User-defined functions can be defined on columns of user-defined types. You can also use these types can as argument types for stored procedures, as described in Using Data-Aware Stored Procedures on page 163. Note: You cannot register a custom .NET type as a user-defined type in SQLFire. The class of a user-defined type must implement the java.io.Serializable interface, and it must be declared to SQLFire by means of a CREATE TYPE statement. You can install user-defined type classes to SQLFire as part of a JAR file installation, as described in Storing and Loading JAR Files in SQLFire on page 131. The key to designing a good user-defined type is to remember that data evolves over time, just like code. A good user-defined type has version information built into it. This allows the user-defined data to upgrade itself as the application changes. For this reason, it is a good idea for a user-defined type to implement java.io.Externalizable and not just java.io.Serializable. Although the SQL standard allows a Java class to implement only java.io.Serializable, this is bad practice for the following reasons: • Recompilation - If the second version of your application is compiled on a different platform from the first version, then your serialized objects may fail to deserialize. This problem and a possible workaround are discussed in the "Version Control" section near the end of this Serialization Primer and in the last paragraph of the header comment for java.io.Serializable. 177 Developing Applications with SQLFire • Evolution - Your tools for evolving a class which simply implements java.io.Serializable are very limited. Fortunately, it is easy to write a version-aware UDT which implements java.io.Serializable and can evolve itself over time. For example, here is the first version of such a class: package com.acme.types; import java.io.*; import java.math.*; public class Price implements Externalizable { // initial version id private static final int FIRST_VERSION = 0; public String currencyCode; public BigDecimal amount; // zero-arg constructor needed by Externalizable machinery public Price() {} public Price( String currencyCode, BigDecimal amount ) { this.currencyCode = currencyCode; this.amount = amount; } // Externalizable implementation public void writeExternal(ObjectOutput out) throws IOException { // first write the version id out.writeInt( FIRST_VERSION ); // now write the state out.writeObject( currencyCode ); out.writeObject( amount ); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { // read the version id int oldVersion = in.readInt(); if ( oldVersion < FIRST_VERSION ) { throw new IOException( "Corrupt data stream." ); } if ( oldVersion > FIRST_VERSION ) { throw new IOException( "Can't deserialize from the future." ); } currencyCode = (String) in.readObject(); amount = (BigDecimal) in.readObject(); } } After this, it is easy to write a second version of the user-defined type which adds a new field. When old versions of Price values are read from the database, they upgrade themselves on the fly. Changes are shown in bold: package com.acme.types; 178 vFabric SQLFire User's Guide Programming User-Defined Types import java.io.*; import java.math.*; import java.sql.*; public class Price implements Externalizable { // initial version id private static final int FIRST_VERSION = 0; private static final int TIMESTAMPED_VERSION = FIRST_VERSION + 1; private static final Timestamp DEFAULT_TIMESTAMP = new Timestamp( 0L ); public String currencyCode; public BigDecimal amount; public Timestamp timeInstant; // 0-arg constructor needed by Externalizable machinery public Price() {} public Price( String currencyCode, BigDecimal amount, Timestamp timeInstant ) { this.currencyCode = currencyCode; this.amount = amount; this.timeInstant = timeInstant; } // Externalizable implementation public void writeExternal(ObjectOutput out) throws IOException { // first write the version id out.writeInt( TIMESTAMPED_VERSION ); // now write the out.writeObject( out.writeObject( out.writeObject( state currencyCode ); amount ); timeInstant ); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { // read the version id int oldVersion = in.readInt(); if ( oldVersion < FIRST_VERSION ) { throw new IOException( "Corrupt data stream." ); } if ( oldVersion > TIMESTAMPED_VERSION ) { throw new IOException( "Can't deserialize from the future." ); } currencyCode = (String) in.readObject(); amount = (BigDecimal) in.readObject(); if ( oldVersion >= TIMESTAMPED_VERSION ) { timeInstant = (Timestamp) in.readObject(); } else { timeInstant = DEFAULT_TIMESTAMP; } 179 Developing Applications with SQLFire } } An application needs to keep its code in sync across all tiers. This is true for all Java code which runs both in the client and in the server. This is true for functions and procedures which run in multiple tiers. It is also true for user-defined types which run in multiple tiers. The programmer should code defensively for the case when the client and server are running different versions of the application code. In particular, the programmer should write defensive serialization logic for user-defined types so that the application gracefully handles client/server version mismatches. 180 vFabric SQLFire User's Guide Chapter 29 Using Result Sets and Cursors A result set maintains a cursor, which points to its current row of data. You can use a result set to step through and process the rows one by one. In SQLFire, any SELECT statement generates a cursor that can be controlled using a java.sql.ResultSet object. SQLFire does not support SQL-92's DECLARE CURSOR language construct to create cursors, but it does support positioned deletes and positioned updates with updatable cursors. Note: This topic was adapted from the Apache Derby documentation source, and is subject to the Apache license: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Non-updatable, Forward-Only Result Sets The simplest result set that vFabric SQLFire supports cannot be updated, and has a cursor that moves only one way, forward. This example is an excerpt from a sample JDBC application that generates a result set with a simple SELECT statement and then processes the rows. Connection conn = DriverManager.getConnection( "jdbc:sqlfire://myHostName:1527/"); Statement s = conn.createStatement(); s.execute("set schema 'SAMP'"); //note that autocommit is on--it is on by default in JDBC ResultSet rs = s.executeQuery( "SELECT empno, firstnme, lastname, salary, bonus, comm " + "FROM samp.employee"); 181 Developing Applications with SQLFire /** a standard JDBC ResultSet. It maintains a * cursor that points to the current row of data. The cursor * moves down one row each time the method next() is called. * You can scroll one way only--forward--with the next() * method. When auto-commit is on, after you reach the * last row the statement is considered completed * and the transaction is committed. */ System.out.println( "last name" + "," + "first name" + ": earnings"); /* here we are scrolling through the result set with the next() method.*/ while (rs.next()) { // processing the rows String firstnme = rs.getString("FIRSTNME"); String lastName = rs.getString("LASTNAME"); BigDecimal salary = rs.getBigDecimal("SALARY"); BigDecimal bonus = rs.getBigDecimal("BONUS"); BigDecimal comm = rs.getBigDecimal("COMM"); System.out.println( lastName + ", " + firstnme + ": " + (salary.add(bonus.add(comm)))); } rs.close(); // once we've iterated through the last row, // the transaction commits automatically and releases //shared locks s.close(); Updatable Result Sets You update result sets in vFabric SQLFire by using result set update methods (updateRow(),deleteRow() and insertRow()), or by using positioned update or delete queries. SQLFire supports updatable result sets that are both scrollable and non-scrollable (forward-only). Requirements for Updatable Result Sets Only specific SELECT statements- simple accesses of a single table-allow you to update or delete rows as you step through them. To create an updatable result set, you must use a JDBC peer client connection to execute a query that specifies the FOR UPDATE clause. For more information, see SELECT on page 542 and FOR UPDATE Clause on page 547. See also SQL Language Limitations on page 765 for information about limitations with updatable results. Forward-Only Updatable Result Sets A forward-only updatable result set maintains a cursor that can move in only one direction (forward), and also update rows. To create a forward only updatable result set, you create a statement with concurrency mode ResultSet.CONCUR_UPDATABLE and type ResultSet.TYPE_FORWARD_ONLY. Note: The default type is ResultSet.TYPE_FORWARD_ONLY. • Example of Forward-Only Updatable Result Set on page 183 • Visibility of Changes on page 183 182 vFabric SQLFire User's Guide Using Result Sets and Cursors • Conflicting Operations on page 183 Example of Forward-Only Updatable Result Set Example of using ResultSet.updateXXX() + ResultSet.updateRow() to update a row: Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); ResultSet uprs = stmt.executeQuery( "SELECT FIRSTNAME, LASTNAME, WORKDEPT, BONUS " + "FROM EMPLOYEE"); while (uprs.next()) { int newBonus = uprs.getInt("BONUS") + 100; uprs.updateInt("BONUS", newBonus); uprs.updateRow(); } Example of using ResultSet.deleteRow() to delete a row: Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); ResultSet uprs = stmt.executeQuery( "SELECT FIRSTNAME, LASTNAME, WORKDEPT, BONUS " + "FROM EMPLOYEE"); while (uprs.next()) { if (uprs.getInt("WORKDEPT")==300) { uprs.deleteRow(); } } Visibility of Changes • After an update or delete is made on a forward-only result set, the result set's cursor is no longer on the row just updated or deleted, but moves immediately before the next row in the result set. (It is necessary to move to the next row before any further row operations are allowed.) This means that changes made by ResultSet.updateRow() and ResultSet.deleteRow() are never visible. • If a row has been inserted (for example, using ResultSet.insertRow()), then it may be visible in a forward-only result set. Conflicting Operations The current row of the result set cannot be changed by other transactions, because it will be locked with an update lock. Result sets that are held open after a commit must move to the next row before allowing any operations on it . Some conflicts may prevent the result set from doing updates and deletes. For example, if the current row is deleted by a statement in the same transaction, then calls to ResultSet.updateRow() cause an exception because the cursor is no longer positioned on a valid row. Scrollable, Updatable Result Sets A scrollable, updatable result set maintains a cursor that can both scroll and update rows. SQLFire only supports Scrollable Insensitive Result Sets. To create a scrollable insensitive result set that is updatable, you create the statement with concurrency mode ResultSet.CONCUR_UPDATABLE and type ResultSet.TYPE_SCROLL_INSENSITIVE. • Examples of Scrollable, Updatable Result Sets on page 183 183 Developing Applications with SQLFire • Visibility of Changes on page 184 • Conflicting Operations on page 185 Examples of Scrollable, Updatable Result Sets Example of using result set update methods to update a row: Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet uprs = stmt.executeQuery( "SELECT FIRSTNAME, LASTNAME, WORKDEPT, BONUS " + "FROM EMPLOYEE"); uprs.absolute(5); // update the fifth row int newBonus = uprs.getInt("BONUS") + 100; uprs.updateInt("BONUS", newBonus); uprs.updateRow(); Example of using ResultSet.deleteRow() to delete a row: Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet uprs = stmt.executeQuery( "SELECT FIRSTNAME, LASTNAME, WORKDEPT, BONUS " + "FROM EMPLOYEE"); uprs.last(); uprs.relative(-5); // moves to the 5th from the last row uprs.deleteRow(); Visibility of Changes • Changes caused by other statements, triggers and other transactions (others) are considered as other changes, and are not visible in scrollable insensitive result sets. • Own updates and deletes are visible in SQLFire scrollable insensitive result sets. Note: SQLFire handles changes made using positioned updates and deletes as own changes, so when made via a result set's cursor such changes are also visible in that result set. • Rows inserted to the table may become visible in the result set. • ResultSet.rowDeleted() returns true if the row has been deleted using the cursor or result set. It does not detect deletes made by other statements or transactions. Note that the method will also work for result sets with concurrency CONCUR_READ_ONLY if the underlying result set is FOR UPDATE and a cursor was used to delete the row. • ResultSet.rowUpdated() returns true if the row has been updated using the cursor or result set. It does not detect updates made by other statements or transactions. Note that the method will also work for result sets with concurrency CONCUR_READ_ONLY if the underlying result set is FOR UPDATE and a cursor was used to update the row. • Note: Both ResultSet.rowUpdated() and ResultSet.rowDeleted() return true if the row first is updated and later deleted. 184 vFabric SQLFire User's Guide Using Result Sets and Cursors Please be aware that even if changes caused by others are not visible in the result set, SQL operations, including positioned updates, which access the current row will read and use the row data as it is in the database, not as it is reflected in the result set. Conflicting Operations A conflict may occur in scrollable insensitive result sets if a row is updated/deleted by another committed transaction, or if a row is updated by another statement in the same transaction. The row which the cursor is positioned on is locked, however once it moves to another row, the lock may be released depending on transaction isolation level. This means that rows in the scrollable insensitive result set may have been updated/deleted by other transactions after they were fetched. Because the result set is insensitive, it will not detect the changes made by others. When doing updates using the result set, conflicting changes on the columns being changed will be overwritten. Some conflicts may prevent the result set from doing updates/deletes: • The row has been deleted after it was read into the result set: Scrollable insensitive result sets will give a warning with SQLState 01001 . • The table has been compressed: Scrollable insensitive result sets will give a warning with SQLState 01001. A compress conflict may happen if the cursor is held over a commit. This is because the table intent lock is released on commit, and not reclaimed until the cursor moves to another row. To avoid conflicts with other transactions, you may increase the transaction isolation level to repeatable read or serializable. This makes the transaction hold locks on the rows that have been read until the transaction commits. Inserting Rows with Updatable Result Sets Updatable result sets can be used to insert rows to the table, by using ResultSet.insertRow(). When you insert a row, you must give a value to each column in the new row that does not allow a null value and does not have a default value. If the inserted row satisfies the query predicate, it becomes visible in the result set. Example of using ResultSet.insertRow() to insert a row: Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); ResultSet uprs = stmt.executeQuery( "SELECT firstname, lastname, workdept, bonus " + "FROM employee"); uprs.moveToInsertRow(); uprs.updateString("FIRSTNAME", "Andreas"); uprs.updateString("LASTNAME", "Korneliussen"); uprs.updateInt("WORKDEPT", 123); uprs.insertRow(); uprs.moveToCurrentRow(); Naming or Accessing the Name of a Cursor There is no SQL language command to assign a name to a cursor. You can use the JDBC setCursorName method to assign a name to a ResultSet that allows positioned updates and deletes. You assign a name to a ResultSet with the setCursorName method of the Statement interface. You assign the name to a cursor before executing the Statement that will generate it. Statement s3 = conn.createStatement(); // name the statement so we can reference the result set // it generates s3.setCursorName("UPDATABLESTATEMENT"); // we will be able to use the following statement later 185 Developing Applications with SQLFire // to access the current row of the cursor // a result set needs to be obtained prior to using the // WHERE CURRENT syntax ResultSet rs = s3.executeQuery("select * from FlightBookings FOR UPDATE of number_seats"); PreparedStatement ps2 = conn.prepareStatement( "UPDATE FlightBookings SET number_seats = ? " + "WHERE CURRENT OF UPDATABLESTATEMENT"); Typically, you do not assign a name to the cursor, but let the system generate one for you automatically. You can determine the system-generated cursor name of a ResultSet generated by a SELECT statement using the ResultSet class's getCursorName method. PreparedStatement ps2 = conn.prepareStatement( "UPDATE employee SET bonus = ? WHERE CURRENT OF "+ Updatable.getCursorName()); Extended Example of an Updatable Result Set Connection conn = DriverManager.getConnection("jdbc:sqlfire://myHostName:1527/"); conn.setAutoCommit(false); // Create the statement with concurrency mode CONCUR_UPDATABLE // to allow result sets to be updatable Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE, ResultSet.CLOSE_CURSORS_AT_COMMIT); // Updatable statements have some requirements // for example, select must be on a single table ResultSet uprs = stmt.executeQuery( "SELECT FIRSTNME, LASTNAME, WORKDEPT, BONUS " + "FROM EMPLOYEE FOR UPDATE of BONUS"); // Only bonus can be updated String theDept="E21"; while (uprs.next()) { String firstnme = uprs.getString("FIRSTNME"); String lastName = uprs.getString("LASTNAME"); String workDept = uprs.getString("WORKDEPT"); BigDecimal bonus = uprs.getBigDecimal("BONUS"); if (workDept.equals(theDept)) { // if the current row meets our criteria, // update the updatable column in the row uprs.updateBigDecimal("BONUS", bonus.add(BigDecimal.valueOf(250L))); uprs.updateRow(); System.out.println("Updating bonus for employee:" + firstnme + lastName); } } conn.commit(); // commit the transaction // close object uprs.close(); 186 vFabric SQLFire User's Guide Using Result Sets and Cursors stmt.close(); // Close connection if the application does not need it any more conn.close(); Scrollable Insensitive Result Sets JDBC provides two types of result sets that allow you to scroll in either direction or to move the cursor to a particular row. SQLFire supports one of these types: scrollable insensitive result sets (ResultSet.TYPE_SCROLL_INSENSITIVE). When you use a result set of type of type ResultSet.TYPE_SCROLL_INSENSITIVE, SQLFire materializes rows from the first one in the result set up to the one with the biggest row number as the rows are requested. The materialized rows are backed to disk if necessary, to avoid excessive memory usage. Insensitive result sets, in contrast to sensitive result sets, cannot see changes made by others on the rows that have materialized. SQLFire allows updates of scrollable insensitive result sets, as described in Visibility of Changes on page 184. (SQLFire also allows updates of forward-only result sets.) Note: SQLFire does not support result sets of type ResultSet.TYPE_SCROLL_SENSITIVE. //autocommit does not have to be off because even if //we accidentally scroll past the last row, the implicit commit //on the the statement will not close the result set because result sets //are held over commit by default conn.setAutoCommit(false); Statement s4 = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); s4.execute("set schema 'SAMP'"); ResultSet scroller=s4.executeQuery( "SELECT sales_person, region, sales FROM sales " + "WHERE sales > 8 ORDER BY sales DESC"); if (scroller.first()) { // One row is now materialized System.out.println("The sales rep who sold the highest number" + " of sales is " + scroller.getString("SALES_PERSON")); } else { System.out.println("There are no rows."); } scroller.beforeFirst(); scroller.afterLast(); // By calling afterlast(), all rows will be materialized scroller.absolute(3); if (!scroller.isAfterLast()) { System.out.println("The employee with the third highest number " + "of sales is " + scroller.getString("SALES_PERSON") + ", with " + scroller.getInt("SALES") + " sales"); } if (scroller.isLast()) { System.out.println("There are only three rows."); } if (scroller.last()) { System.out.println("The least highest number " + "of sales of the top three sales is: " + scroller.getInt("SALES")); 187 Developing Applications with SQLFire } scroller.close(); s4.close(); conn.commit() conn.close(); System.out.println("Closed connection"); Result Sets and Autocommit Issuing a commit causes all result sets on your connection to be closed. A JDBC application is not required to have autocommit off when using update methods on an updatable result set. However, positioned updates and deletes cannot be used in combination with autocommit. 188 vFabric SQLFire User's Guide Part 6 Caching Data with vFabric SQLFire Caching Data with vFabric SQLFire describes how to use SQLFire as a high-performance cache for an existing, traditional RDBMS system. This guide describes the various cache strategies and explains how to implement and use eviction features, listeners, and cache plug-ins to implement a cache. Topics: • • • • • • • SQLFire Cache Strategies Using a RowLoader to Load Existing Data Evicting Table Data from SQLFire Handling DML Events Synchronously Handling DML Events Asynchronously Using DBSynchronizer to Apply DML to an RDBMS Suppressing Event Callbacks for a vFabric SQLFire Connection 189 Chapter 30 SQLFire Cache Strategies You can deploy SQLFire as a distributed cache for data that is managed in a traditional relational database system. SQLFire offers several strategies for using the product as a database cache. • Considerations for Auto-Generated Keys on page 191 • Lazy-Loading the Cache on page 191 • Preloading Strategies on page 191 • Integration with Hibernate on page 192 • Exporting and Transforming an Existing Schema on page 192 Considerations for Auto-Generated Keys If cached tables require automatic generation of identity column values, then you should use SQLFire to automatically generate the key values but disable generated keys in the backend database. If the backend database also generates key values, then inserts can fail if SQLFire has already generated the key. Note: SQLFire supports automatic generation of identity column values, but it does not support generating a sequence of key values. If a sequence is required, then consider using a stored procedure to obtain the next sequence value from the backend database before inserting the row in SQLFire. Lazy-Loading the Cache Application query requests are first attempted in SQLFire. On a miss, a loader that implements lazy loading is invoked that can fetch the data from a backend database. SQLFire only supports primary key-based queries when the table is lazily loaded. It is impractical (too expensive) to determine the subset of the rows missing in SQLFire and construct a query to the backend database that only fetches the missing rows. It is also typical for applications to configure least-recently-used (LRU) caching where the cache optimizes the available memory by evicting the least frequently used rows. Applications can only issue primary key-based queries on tables that are configured for eviction. For more information, see Using a RowLoader to Load Existing Data on page 193. All updates can be synchronously or asynchronously written back to the database using a 'writer' or the built in Using DBSynchronizer to Apply DML to an RDBMS on page 209. For tables that are identical in structure to the backend database, applications can asynchronously "write behind" if you configure the database URL for the backend database. Preloading Strategies SQLFire offers several caching strategies that involve preloading data. • Preload database. Load the entire database at bootstrap time into SQLFire. If all updates are going through SQLFire, it is unnecessary to resynchronize the state from the backend database. The data bootstrapping process is outlined below. With this choice, the tables are loaded with the entire data set from the backend database and all queries can directly be executed on SQLFire data stores. 191 Caching Data with vFabric SQLFire • Preload "hot" data and lazy-load the rest. If the data set in the backend database is very large, a better option would be to maintain all the "hot" tables in SQLFire and lazy load the historical data into "historical" tables. With this design, the entire supported SQL syntax can be used on fully populated "hot" tables, but, only primary key based queries can be issued on historical tables. Typically, these historical tables will be configured for LRU eviction. Integration with Hibernate SQLFire can also be integrated in object relational mapping products such as Hibernate and provide an L2 cache entire query result sets can be cached in SQLFire. Updates done using the Hibernate API will be synchronously propagated to the database and query result sets will be invalidated in SQLFire. See vFabric SQLFire Hibernate Dialect for information about using the SQLFire dialect file with your Hibernate projects. Exporting and Transforming an Existing Schema Application developers can use a tool such as Exporting and Importing Data with vFabric SQLFire to export an existing relational database schema, transform it to SQLFire, and import the new schema along with data into a SQLFire cluster. 192 vFabric SQLFire User's Guide Chapter 31 Using a RowLoader to Load Existing Data When you use SQLFire as a cache, you can configure a SQL data loader that is triggered to load data from a backend repository on a miss in SQLFire. When an incoming query request for a uniquely-identified row cannot be satisfied by the distributed cache, the loader is invoked to retrieve the data from an external source. SQLFire locks the associated row and prevents concurrent readers that are trying to fetch the same row from overloading the backend database. Note: When a loader is configured for a table, performing a select statement against the table internally fetches and inserts data into a SQLFire table. Because of this behavior, it is possible to receive a constraint violation when you query a table that is configured with a loader (for example, if the loader attempts to insert data from a backend database that violates a table constraint in SQLFire). How SQLFire Invokes a RowLoader SQLFire only invokes a configured RowLoader when certain conditions are met. SQLFire invokes a configured RowLoader when: • A SELECT query is executed against a table with a WHERE clause that includes an equality (=) test for every component that is part of the table's primary key, and • A row for the specified primary key does not exist in memory. Note that it does not matter which columns are requested or used from the resulting rows. For example, consider the following example table definition: CREATE TABLE LoaderTest(id INTEGER, name VARCHAR(10), result VARCHAR(10), primary key (id, name)); In the "LoaderTest" table, columns "id" and "name" form the primary key. Queries that use an equality test on the primary key invoke an attached loader implementation for the table, if the data was not already available in SQLFire. For example, these queries would invoke a loader: SELECT * FROM LoaderTest WHERE id = 5 AND name='Joe'; SELECT result FROM LoaderTest WHERE id = 6 AND name='Sam'; However, these queries would not invoke an attached loader: SELECT result FROM LoaderTest WHERE id < 6 AND name='Sam'; SELECT * FROM LoaderTest; SELECT * FROM LoaderTest WHERE id = 5; In the above examples, none of the SELECT statements use an equality test for all components of the primary key (both "id" and "name"). 193 Caching Data with vFabric SQLFire Implementing the RowLoader Interface To create a RowLoader, you define a class that implements the interface com.vmware.sqlfire.callbacks.RowLoader, and then attach your implementation to a table using a system procedure. The implementation then acts as the SQL data loader. Procedure 1. Include a public, static method that takes no parameters, and that returns an instance of the loader. For example: ExampleRowLoader.java package example.callbacks; import java.sql.*; import javax.sql.*; import javax.sql.rowset.*; import com.vmware.sqlfire.callbacks.RowLoader; public class MyRowLoader implements RowLoader{ public static MyRowLoader create() { return new ExampleRowLoader(); } 2. Implement an init(String initStr) method to obtain parameters that are defined when you register your implementation with a table. SQLFire calls your implementation's init() method when the SYS.ATTACH_LOADER procedure is used to register the RowLoader with a table. All parameters are passed in the single String object. 3. SQLFire calls the getRow(String schemaName, String tableName, Object[] primarykey) method implementation to provide the schema name, table name and an array of objects that are the primary key values (in the order presented by the table definition) each time the loader is invoked to fetch data from the external source. Your implementatino of this method must return one of the following: • An object array with one element with the value for each column, including the primary key, in the order defined by the SQLFire table definition. • null, if there is no element found. • An instance of java.sql.ResultSet, possibly the result of a query against another database. Only the first row will be used. The result columns should match the SQLFire table. • An empty java.sql.ResultSet if no element is found. 4. After compiling your RowLoader implementation and adding it to the classpath, register the RowLoader with a table by executing the built-in SYS.ATTACH_LOADER procedure. Using the JDBCRowLoader Example The JDBCRowLoader class provide a sample RowLoader implementation that loads data from archive relational data stores. • Features and Requirements on page 194 • JDBCRowLoader Example Implementation on page 195 Features and Requirements The JDBCRowLoader example has the following features: • It can be implemented for any JDBC data source (provided the driver is available in the classpath of the server) 194 vFabric SQLFire User's Guide Using a RowLoader to Load Existing Data • It can be implemented for any table, although a separate instance of the RowLoader is created for each table. • It pools JDBC Connections and PreparedStatements, with a configurable minimum and maximum number of connections. • It uses the Connection.isReadOnly(true) setting to request that the driver optimize the transaction settings for database reads. A query-string parameter is passed to the JDBCRowLoader to tell it what SQL statement to use against the archive database. This is a required parameter. If the column layout of the archive table matches the column layout of the SQLFire table, you can use SELECT * in the query string. If the column layout of the archive table does not match the column layout of the SQLFire table, you must explicitly provide and order the column names in the SELECT statement so that the result set matches the layout of the SQLFire table. There is no requirement that the schema or table name in SQLFire match the schema and/or table name in the archive database. The elements of the primary key are passed into the JDBCRowLoader when it is invoked, in the order that the columns are defined in the SQLFire table. They will be passed as parameters into the PreparedStatement in that order, so you must structure the WHERE clause of the query-string so that the elements are passed in the correct order. Accepted parameters with examples: • url=jdbc:oracle:thin:@localhost:1521:XE (required) • query-string=SELECT * FROM LoaderArchive WHERE id=? AND name=? (required) • user=app • password=app • min-connections=1 • max-connections=5 • connection-timeout=3000 (milliseconds) All properties are also passed to the JDBC connection when it is created. JDBCRowLoader Example Implementation SQLFire installs a sample JDBCRowLoader implementation in vFabric_SQLFire_11_bNNNNN/examples/JDBCRowLoader.java. Note that this example requires gemfire.jar (from the vFabric GemFire product) in order to run. 195 Chapter 32 Evicting Table Data from SQLFire You can configure tables with least recently used (LRU) eviction and expiration to manage the amount of data that is kept in a SQLFire system. Use LRU eviction to remove table data from memory, or to persist the overflow data in a disk store. How LRU Eviction Works SQLFire keeps a table's data use under a specified level by removing the least recently used (LRU) data to free memory for new data. You configure table eviction settings based on entry count, the percentage of available heap, or the absolute memory usage of table data. You also configure the action that SQLFire should take to evict data: destroy the data or overflow data to a disk store (creating a "overflow table"). When SQLFire determines that adding or updating a row would take the table over the specified level, it overflows or removes as many older rows as it needed to make room. For entry count eviction, this means a one-to-one trade of an older row for the newer one. For the memory settings, the number of older rows that need to be removed to make space depends entirely on the relative sizes of the older and newer entries. Eviction controllers monitor the table and memory use and, when the limit is reached, remove older entries to make way for new data. For JVM heap percentage, the controller used is the SQLFire resource manager, configured in conjunction with the JVM's garbage collector for optimum performance. When eviction is enabled, SQLFire manages table rows in a hash map-like structure where the primary key value is used as the key for all other column data in the row. When a row is evicted, the primary key value remains in memory while the remaining column data is evicted. To configure LRU eviction, see Create a Table with Eviction Settings on page 198 and CREATE TABLE on page 505.After you configure eviction features, you can install a Using a RowLoader to Load Existing Data and/or synchronous Handling DML Events Synchronously to access an external data source, effectively allowing SQLFire to be used as a cache. For limitations of this capability, see Limitations of Eviction on page 197. Limitations of Eviction LRU eviction is only effective for operations that operate on a primary key value. Consider these limitations before you implement LRU eviction in your system: • The capability to synchronize with an external data source is only effective for select/update/delete operations that query data by primary key. Accessing data by other criteria may result in incomplete results, because a RowLoader is only invoked on primary key queries. • If you configure a table with the DESTROY eviction action, you must ensure that all queries against the table filter results using a primary key value. Queries that do not filter on a primary key may yield partial results if rows are destroyed on eviction. This limitation does not apply to tables that are configured with the OVERFLOW eviction action. 197 Caching Data with vFabric SQLFire • You cannot create a foreign key reference to a table that is configured for eviction or expiration with the DESTROY action. This limitation does not apply to tables that are configured with the OVERFLOW eviction action. See EVICTION BY Clause on page 518 for more information. • Some applications may benefit from evicting rows to disk in order to reduce heap space. However, enabling eviction also increases the per-row overhead that SQLFire requires to perform LRU eviction for the table. As a general rule, table eviction is only helpful for conserving memory if the non-primary key columns in a table are large: 100 bytes or more. • An UPDATE will not occur on a row that has been evicted or has expired from the cache with the DESTROY action. This limitation does not apply to tables that are configured with the OVERFLOW eviction action. • An INSERT will succeed if an identical row (based on primary key) has been previously evicted or expired from the cache with the DESTROY action, but the row still exists in the external data store. Eviction in Partitioned Tables In partitioned tables, SQLFire removes the oldest entry it can find in the bucket where the new entry operation is being performed. SQLFire maintains LRU entry information on a bucket-by-bucket basis, because the performance cost of maintaining information across the entire partitioned table is too great. SQLFire chooses buckets for LRU eviction in these ways: • For memory and entry count eviction, LRU eviction is done in the bucket where the new row is being added until the overall size of the combined buckets in the member has dropped enough to perform the operation without going over the limit. • For heap eviction, each partitioned table bucket is treated as if it were a separate table, with each eviction action only considering the LRU for the bucket, and not the partitioned table as a whole. Eviction in a partitioned table may leave older entries for the table in other buckets in the local data store as well as in other hosts in the distributed system. It may also leave entries in a primary copy that it evicts from a secondary copy or vice-versa. However, SQLFire synchronizes the redundant copies when an entry with the same primary key is inserted or updated. Create a Table with Eviction Settings Use eviction settings to keep your table within a specified limit, either by removing evicted data completely or by creating an overflow table that persists the evicted data to a disk store. Procedure Follow these steps to configure table eviction settings. Refer to CREATE TABLE on page 505 for details about specifying eviction settings. 1. Decide whether to evict based on: • Entry count (useful if table row sizes are relatively uniform). • Total bytes used. • Percentage of JVM heap used. This uses the SQLFire resource manager. When the manager determines that eviction is required, the manager orders the eviction controller to start evicting from all tables where the eviction criterion is set to LRUHEAPPERCENT. You can configure a global heap percentage for all SQLFire data stores, or configure different heap percentages for one or more server groups. Heap Eviction Configuration Procedures on page 631 describes how to configure the heap percentage. Eviction continues until the resource manager calls a halt. SQLFire evicts the least recently used rows hosted by the member for the table. 2. Decide what action to take when the limit is reached: • Locally destroy the row. 198 vFabric SQLFire User's Guide Evicting Table Data from SQLFire Note: SQLFire does not propagate the DESTROY evict action to configured callback implementations, such as DBSynchronizer. Do not configure eviction with the DESTROY action on a table that has dependent tables (for example, child rows with foreign keys). If a DELETE statement is called for a parent table row that was locally destroyed through eviction, the DELETE succeeds in SQLFire. However, the DELETE operation can later fail in the backend database when DBSynchronizer asynchronously sends the DELETE command, if dependent rows still exist. If eviction with the DESTROY action is required for dependent tables, consider using a trigger or writer implementation to listen for DELETE events on the parent table. The trigger or writer should fail the DELETE operation if child rows are found to exist in the backend database. • Overflow the row data to disk. Note: When you configure an overflow table, only the evicted rows are written to disk. If you restart or shut down a member that hosts the overflow table, the table data that was in memory is lost unless you explicitly configure persistence (or you configure one or more replicas with a partitioned table). See Using Disk Stores to Persist Data on page 85. 3. If you want to overflow data to disk (or persist the entire table to disk), configure a named disk store to use for the overflow data. If you do not specify a disk store when creating an overflow table, SQLFire stores the overflow data in the default disk store. 4. Create the table with the required eviction configuration. For example, to evict using LRU entry count and overflow evicted rows to a disk store: CREATE TABLE Orders(OrderId INT NOT NULL,ItemId INT ) EVICTION BY LRUCOUNT 2 EVICTACTION OVERFLOW 'OverflowDiskStore' ASYNCHRONOUS If you do not specify a disk store, SQLFire overflows table data to the default disk store. To create an overflow table and persist the entire table, so that the entire table is available through peer restarts: CREATE TABLE Orders(OrderId INT NOT NULL,ItemId INT ) EVICTION BY LRUCOUNT 2 EVICTACTION OVERFLOW PERSISTENT 'OverflowDiskStore' ASYNCHRONOUS The table uses the same named disk store for both overflow and persistence. To create a table that simply removes evicted data from memory without persisting the evicted data, use the DESTROY eviction action. For example: CREATE TABLE Orders(OrderId INT NOT NULL,ItemId INT ) EVICTION BY LRUMEMSIZE 1000 EVICTACTION DESTROY 199 Chapter 33 Handling DML Events Synchronously SQLFire provides synchronous cache plug-in mechanisms to handle cache events. Writer and Listener Cache Plug-ins You can implement two types of synchronous cache plug-ins: writers and listeners. Writer and listener cache plug-ins operate in the following ways: • Listener—A listener enables you to receive after-event notifications of changes to a table (insert, update and delete). Any number of listeners can be defined for the same table. Listener callbacks are called synchronously, so they will cause the DML operation to block if the callback blocks. • Writer—A cache writer is an event handler that synchronously handles changes to a table before those changes take place. The main use of a cache writer is to keep external data sources synchronized with a table in SQLFire, or to perform other checking or work before a DML operation takes place in SQLFire. A cache writer provides write-through caching with your external data source. Unlike listeners, only one writer can be attached to a table. When the table is about to to be modified because of an insert, update, or a delete, SQLFire informs the writer of the pending operation using the callback. The writer can choose to disallow the operation by throwing a SQLException. The writer callback is called synchronously and will block the operation if the callback blocks. Note: SQLFire does not check primary or unique key constraints before invoking a writer callback. You attach writers and listeners to tables by using the SYS.ATTACH_WRITER and SYS.ADD_LISTENER built-in system procedures. Both listeners and writers must be implementations of the EventCallback interface. The main method of the interface is the onEvent method, which is invoked in both writer and listener implementations. The Event object which is passed with the callback gives the following information: • The type of the event. TYPE.BEFORE_INSERT, TYPE.BEFORE_UPDATE and TYPE.BEFORE_DELETE are provided to writers to indicate whether an insert, update, or delete is about to take place. Similarly listeners receive TYPE.AFTER_INSERT, TYPE.AFTER_UPDATE and TYPE.AFTER_DELETE. • The old row as a List (for an update or delete operation). • The new row as a List (for an insert or update operation). • The ResultSetMetaData (metadata of the table). • Information about whether the event's source was local. • GetModifiedColumns() - the int[] of 1-based column positions for the columns that were updated. • The primary key of the row being modified as an object[] . 201 Caching Data with vFabric SQLFire SQLFire API on page 477 provides additional information and examples for using callbacks. Example Writer Implementation SQLFire installs a sample writer implementation in vFabric_SQLFire_11_bNNNNN/examples/EventCallbackWriterImpl.javam. This writer implementation can be used to perform writes to any JDBC data source, if the appropriate driver is available in the classpath. See the example comments for more information. Example Listener Implementation In this listener implementation of the EventCallBack interface, the listener checks the event type and, for AFTER_INSERT events, multiplies each column by a factor and then inserts into a foreign table. SYS.ADD_LISTENER on page 626 shows example code for deploying this listener to a table. package testpackage; public class EventCallBackListenerImpl implements EventCallback { private private private private String foreigntablename; int factor; Connection conn; PreparedStatement ps; public EventCallBackListenerImpl() { } public void close() throws SQLException { } // The init method expects the initStr to contain the name of the // foreign table and the factor. Eg: "emp.ftable:3" public void init(String initStr) throws SQLException { String[] arr = initStr.split(":"); this.foreigntablename = arr[0]; this.factor = Integer.parseInt(arr[1]); this.conn = getConnection(); this.ps = this.conn.prepareStatement( "insert into "+this.foreigntablename+" values(?, ?, ?)"); } public void onEvent(Event event) throws SQLException { if (if ((event.getType() == Type.AFTER_INSERT)) { int size = event.getNewRow().size(); assert size == 3 : "expected the size to be 3"; List colValues = event.getNewRow(); int one = ((Integer)colValues.get(0)).intValue() * this.factor; int two = ((Integer)colValues.get(1)).intValue() * this.factor; int three = ((Integer)colValues .get(2)).intValue() * this.factor; this.ps.setInt(1, one); this.ps.setInt(2, two); this.ps.setInt(3, three); this.ps.executeUpdate(); } } 202 vFabric SQLFire User's Guide Chapter 34 Handling DML Events Asynchronously An AsyncEventListener receives callbacks on the execution of data manipulation language (DML) statements (create, update, and delete operations) in SQLFire. In a caching deployment, you can use an AsyncEventListener to analyze data in DML statements and take desired actions such as persisting the data in a specific format. How the AsyncEventListener Works An AsyncEventListener instance is serviced by its own dedicated thread in which a callback method is invoked. Events that correspond to DML operations are placed in an internal queue, and the dedicated thread dispatches a batch of events at a time to the user-implemented callback class. The frequency of dispatching events is governed by the configuration of the AsyncEventListener in SQLFire. To receive DML callbacks, you create a class that implements the AsyncEventListener interface. The callback method processEvents(List events) provides information related to manipulated rows, such as the new row values. Each Event object provides following information. Event Information Description Type of Event Object of EVENT.Type enumeration. This can be AFTER_INSERT, AFTER_UPDATE, AFTER_DELETE, BEFORE_DELETE, BEFORE_INSERT, BEFORE_UPDATE, BULK_DML, or BULK_INSERT depending upon the type of CRUD operation. Schema and Table Name The schema and table name for the current operation. Old Row A result set of column values representing the old row that is being updated. New Row A result set of column values representing the new rows that are being inserted or updated. Table MetaData Information about the type, properties, and positions of the columns being returned. Primary Key A result set representing the primary key columns of the changed rows. Note: Certain data consistency problems can occur if multiple threads update data that is queued to an AsyncEventListener implementation. See No Ordering Guarantee for DML in Separate Threads on page 156. Implementation Requirements Before you implement an AsynchEventListener, be aware of the requirements and guidelines. 203 Caching Data with vFabric SQLFire • All AsyncEventListener implementations should check for the possibility that an existing database connection may have been closed due to an earlier exception. For example, check for Connection.isClosed() in a catch block and re-create the connection as needed before performing further operations. The DBSynchronizer implementation in SQLFire automatically performs this type of check before reusing a connection. • An AsyncEventListener implementation must be installed on one or more members of the SQLFire system. You can install AsyncEventListeners only on data stores (peers configured with the property host-data set to " true"). • You can install a listener on more than one member to provide high availability and guarantee delivery for events, in the event that a SQLFire member with an active AsyncEventListener shuts down. At any given time only one member has an active thread for dispatching events. The threads on other members remain on standby for redundancy. • Install no more than one standby listener (redundancy of at most one) for performance and memory reasons. • To preserve pending events through member shutdowns, configure SQLFire to persist the internal queue of an AsyncEventListener to an available Using Disk Stores to Persist Data. By default, any pending events that reside in the internal queue of an AsyncEventListener are lost if the active listener's SQLFire member shuts down. • To ensure high availability and reliable delivery of events, configure the event queue to be both persistent and redundant. • If your listener implementation must deliver user credentials to an outside data source, consider encrypting the credentials using sqlf encrypt-password with the external option. You can then supply the encrypted password (rather than a clear-text password) to your listener via initialization parameters. The listener can then use the AsyncEventHelper.decryptPassword method to decrypt the password before in order to connect to the outside data source. Implementing an AsyncEventListener You implement an AsyncEventListener by defining a class that implements the AsynchEventListener interface, installing the AsynchEventListener configuration, and associating a table with it. Note: SQLFire also includes sample code for the built-in DBSynchronizer listener, which uses the latest AsyncEventListener API. This sample listener is installed in the examples/com/vmware/sqlfire/callbacks subdirectory of your SQLFire installation directory. This also includes source code for the AsyncEventHelper class. Keep in mind that you cannot compile the AsyncEventHelper.java code as-is, because it uses internal SQLFire classes. You can either extend the installed AsyncEventHelper implementation or copy the public API code from the example into your own class, modifying the code as necessary to create a custom helper class. The main steps are detailed in the sections that follow. Before you begin, read Implementation Requirements on page 203. 1. 2. 3. 4. 5. Implement the AsyncEventListener Interface on page 205. Install the AsyncEventListener Configuration on page 206. Start the AsyncEventListener Configuration on page 207. Associate a Table with an AsyncEventListener Configuration on page 207. Stop or Remove an AsyncEventListener Configuration on page 208 The example procedures show how to configure an AsyncEventListener with redundancy 1 in a SQLFire system having one peer-client member and three data store members. Two data stores "DataStore1" and "DataStore2" are available in server group "SG1." The AsyncEventListener will be installed on only those members that belong to server group 'SG1'. A single table, "TESTTABLE" is associated with the AsyncEventListener. When testing your own AsyncEventListener implementation you will also need to stop the listener configuration. Stop or Remove an AsyncEventListener Configuration on page 208 describes this process. 204 vFabric SQLFire User's Guide Handling DML Events Asynchronously Implement the AsyncEventListener Interface Define a class that implements the http://www.vmware.com/support/developer/vfabric-sqlfire/111-api/com/vmware/sqlfire/callbacks/AsyncEventListener.html interface. For example: package user.application; import import import import import import java.io.FileNotFoundException; java.io.FileOutputStream; java.io.IOException; java.sql.ResultSetMetaData; java.util.Iterator; java.util.List; import com.vmware.sqlfire.callbacks.AsyncEventListener; import com.vmware.sqlfire.callbacks.Event; public class TestAsyncEvenListener implements AsyncEventListener { private FileOutputStream fos; public void close() { try { this.fos.close(); } catch (IOException e) { //handle exception } } public void init(String filePath) { try { this.fos = new FileOutputStream(filePath); } catch (FileNotFoundException e) { //handle exception } } public boolean processEvents(List events) { try { Iterator itr = events.iterator(); Event.Type evType = null; for (Event event : events) { ResultSetMetaData rsmd = event.getResultSetMetaData(); String schemaName = rsmd.getSchemaName(1 /*from column # 1*/); String tableName = rsmd.getTableName(1 /*from column # 1*/); evType = event.getType(); //The primary key could be either a single value for single column // primary key or could be an Object[] in case of Composite primary key. //For tables without primary key defined, the value returned is a Long // which uniquely identifies the row. User can map rows created/updated/deleted 205 Caching Data with vFabric SQLFire // using this value. Object pk = event.getPrimaryKey(); switch (evType) { case AFTER_INSERT: List rowInserted = event.getNewRow(); int i =1; for (Object colVal : rowInserted) { String columnName = rsmd.getColumnName(i); // use the column name & value given by colVal to process the field } //process the row , may be persist to file. break; case AFTER_UPDATE: List rowUpdated = event.getNewRow(); //Modified column's column position is given by the below API. //The unmodified cols are null List modifiedCols = event.getModifiedColumns(); for (int colNum : modifiedCols) { //The column number which is modified is given by colNum. //Obtain info about modified column String colName = rsmd.getColumnName(colNum); //Obtain the modified value of the column //Notice that the value is obtained at position colNum -1, as the //List containing values is zero based while column position in table // is 1 based. Object newColNalue = rowUpdated.get(colNum - 1); //process the information using the column name , table name, schema name //& modified value. } break; case AFTER_DELETE: //Utilize the pk , primary key for processing the deleted row. break; } } } catch (Exception e) { //handle exception return false; } return true; } } Install the AsyncEventListener Configuration Install the AsyncEventListener implementation by executing the CREATE ASYNCEVENTLISTENER statement on any member of the SQLFire system. You must specify the server groups on which to deploy the implementation, as well as a unique identification and class name for the implementation. For example: CREATE ASYNCEVENTLISTENER MyListener ( 206 vFabric SQLFire User's Guide Handling DML Events Asynchronously ) LISTENERCLASSNAME 'user.application.TestAsyncEventListener' INITPARAMS '' SERVER GROUPS ( SG1 ); Note: You must include the INITPARAMS argument, even if it defines no parameters. If you send user credentials in the initialization parameters, consider encrypting the password using sqlf encrypt-password with the external option. Note: You can optionally install the AsyncEventListener configuration after you associate a table with the listener name. Make sure that you use the same listener name with both the CREATE ASYNCEVENTLISTNER command and the CREATE TABLE command. This example installs TestAsyncEventListener with the identifier "MyListener" on members of the server group "SG1." See CREATE ASYNCEVENTLISTENER for more information about other parameters to the procedure. Start the AsyncEventListener Configuration After you install the AsyncEventListener implementation, you can start it by specifying the unique identifier for the implementation in the SYS.START_ASYNC_EVENT_LISTENER procedure. For example: java.sql.Connection conn = getConnection(); CallableStatement cs = conn.prepareCall("call SYS.START_ASYNC_EVENT_LISTENER( ? )"); cs.setString(1, "MyID"); cs.execute(); On execution, a thread would service the queue of the AsyncEventListener and dispatch events to the callback class. Associate a Table with an AsyncEventListener Configuration You associate a table with an AsyncEventListener configuration using the AsyncEventListener clause in the table's CREATE TABLE statement. For example, to associate the table "TestTable" with an AsyncEventListenerConfiguration identified by "MyID" use the statement: java.sql.Connection conn = getConnection(); Statement stmt = conn.createStatement(); stmt.execute("CREATE TABLE TESTTABLE (ID int NOT NULL, DESCRIPTION varchar(1024), ADDRESS varchar(1024) ) AsyncEventListener(MyID) " ); Note: Because the associated listener configuration does not have to be available at the time you create the table, SQLFire does not display an error message if the specified listener name does not yet exist. Make sure that you use the same listener name with both the CREATE ASYNCEVENTLISTNER command and the CREATE TABLE command. Note: You can optionally associate the table with an AsyncEventListener configuration after you create the table, using the SQLFire ALTER TABLE statement. 207 Caching Data with vFabric SQLFire Display Installed AsyncEventListeners You can join the SYSTABLES, MEMBERS, and ASYNCEVENTLISTENERS tables to display the listener implementations associated with a table as well as the data store ID on which the listener is installed: select t.*, m.ID DSID from SYS.SYSTABLES t, SYS.MEMBERS m, SYS.ASYNCEVENTLISTENERS a where t.tablename='' and groupsintersect(a.SERVER_GROUPS, m.SERVERGROUPS) and groupsintersect(t.ASYNCLISTENERS, a.ID); See SYSTABLES on page 691 and ASYNCEVENTLISTENERS on page 669. Stop or Remove an AsyncEventListener Configuration To stop a running AsyncEventListener configuration, first use the SYS.WAIT_FOR_SENDER_QUEUE_FLUSH procedure to ensure that no queued events are lost. Then use SYS.STOP_ASYNC_EVENT_LISTENER and specify the identifier to the configuration to stop: java.sql.Connection conn = getConnection(); CallableStatement cs1 = conn.prepareCall("call SYS.WAIT_FOR_SENDER_QUEUE_FLUSH(?,?,?); cs1.setString(1, "MyID"); cs1.setString(2, "TRUE"); cs1.setString(3, "0"); cs1.execute(); CallableStatement cs2 = conn.prepareCall("call SYS.STOP_ASYNC_EVENT_LISTENER( ? )"); cs2.setString(1, "MyID"); cs2.execute(); CallableStatement cs2 = conn.prepareCall("call SYS.STOP_ASYNC_EVENT_LISTENER( ? )"); cs2.setString(1, "MyID"); cs2.execute(); This waits for all queued events to flush, and then stops dispatching events to the callback listener class. Also, the close() method of the Callback AsyncEventListener class is invoked so that the implementation can perform any necessary cleanup. You can also remove a listener implementation from the cluster using DROP ASYNCEVENTLISTENER on page 531. 208 vFabric SQLFire User's Guide Chapter 35 Using DBSynchronizer to Apply DML to an RDBMS DBSynchronizer is a built-in AsyncEventListener implementation that you can use to asynchronously persist data to a third-party, JDBC 4.0-compliant RDBMS. VMWare includes sample code for the DBSynchronizer implementation in the examples/com/vmware/sqlfire/callbacks subdirectory of your SQLFire installation directory. See the README.txt file in that directory for more information. How DBSynchronizer Works You install DBSynchronizer as an AsyncEventListener on multiple data stores, preferably two. The DML statements executed on SQLFire are passed on to the DBSynchronizer and the configured JDBC RDBMS. DBSynchronizer can be installed only on data stores (configured with host-data property set to "true"). Each instance of DBSynchronizer maintains an internal queue to batch up the DML statements and is serviced by its own dedicated thread. This thread picks up DML statements from the queue, and applies them to the external database using prepared statements. • Ensuring High Availability and Reliable Delivery on page 209 • How Failover and Upgrades Affect Synchronization on page 209 Ensuring High Availability and Reliable Delivery Configure the DBSynchronizer queue for both persistence and redundancy to ensure high availability and reliable delivery of events. Installing DBSynchronizer on more than one data store provides high availability. At any given time only one member has a DBSynchronizer thread active for executing DML on the external database. The threads on other members are on standby (redundant) to guarantee execution of DML if the member with the active DBSynchronizer thread fails. Install no more than one standby DBSynchronizer (redundancy of at most one) for performance and memory reasons. By default, any pending DML operations residing in the internal queue of the DBSynchronizer are lost if the active member shuts down. You can avoid losing operations by configuring the internal queue of DBSynchronizer to be persistent. How Failover and Upgrades Affect Synchronization A DML operation may be reapplied to the RDBMS if the member with the active DBSynchronizer thread fails. If the member with the active DBSynchronizer fails while sending a batch of operations, some DML statements in the batch may already have been applied to the RDBMS. On failover, the new DBSynchronizer thread resends 209 Caching Data with vFabric SQLFire the failed batch and reapplies the initial DML operations. When this occurs, the RDBMS may get out-of-synch depending upon the nature of the DML operation, how it modifies table columns, and the presence or absence of column constraints. Note: Failover-related issues can also occur when upgrading SQLFire servers, if clients are actively performing DML on synchronized tables when a server is restarted for manual or rolling upgrades. If the table has any constraint (primary key, unique) defined, the following types of DML operations do not cause out-of-synch problems when they are reapplied during failover: • A create operation that is reapplied to a table with a primary key. A primary key constraint violation occurs and a SQLException is thrown, but DBSynchronizer ignores the exception. • A create or update operation that causes a unique constraint violation. Reapplying a create or update operation causes a duplicate value, violating the unique constraint. DBSynchronizer ignores the SQLException that is thrown in this situation. • A create or update operation that causes a check constraint violation. Reapplying create or an update (for example, incrementing or decrementing a column value) may cause a check constraint to be violated. DBSynchronizer ignores the SQLException that is thrown in this situation. In the preceding cases, the constraints prevent the tables from going out of synch with the SQLFire data. Reapplying certain update operations (such as update T1 set Col1 = 5 where col2 =7) and delete operations (such as delete from T1 where col1 = 5) do not cause out-of-synch problems. However, the following types of DML operations do cause out of synch issues when they are reapplied during failover: • Create operations on a table without a primary key constraint. In this case, reapplying a create operation creates additional rows. • Update operations that modify the column value relative to its current value. Reapplying update operations such as update T1 set col1 = col1 +? where col2 = ? cause the external database to go out-of-synch with the SQLFire data. Restrictions and Limitations This release of SQLFire has several restrictions and limitations on the use of DBSynchronizer. • DBSynchronizer, AsyncEventHelper Example Code SQLFire installs the source code for the built-in DBSynchronizer and AsyncEventHelper classes into the /examples/com/vmware/sqlfire/callbacks directory. This source code is identical to the class implementations that are built into SQLFire. Use the examples to create new classes either by copying and modifying the code for public APIs, or by extending the classes. Keep in mind: • You cannot compile the AsyncEventHelper.java code as-is, because it uses internal SQLFire classes. Either extend the installed AsyncEventHelper implementation or copy the public API code from the example into your own class, modifying the code as necessary to create a custom helper class. • The DBSynchronizer.java file uses no internal classes. However, you must copy the into your own class in order to avoid conflicts with the built-in DBSynchronizer implementation. • Triggers Using triggers with DBSynchronizer is not supported. Triggers that are defined on both the external database and in the SQLFire system can cause multiple executions of trigger-generated DML. • Handling database connectivity problems 210 vFabric SQLFire User's Guide Using DBSynchronizer to Apply DML to an RDBMS If DBSynchronizer encounters an exception while updating or committing to the database, the batch is retained and the DBSynchronizer thread will continue trying to apply the batch until it is successful. • Concurrent DML operations If DML operations are executed concurrently on a SQLFire System that has a foreign key relationship based on parent and child table, a foreign key violation may occur while applying DML operations to the external database. This can occur even if the SQLFire system successfully executed the DML. Although inserts into the parent and child table occur in order in the SQLFire system, the inserts may reach DBSynchronizer in reverse order. To avoid this behavior, perform updates to parent and child tables in a single application thread. See How the AsyncEventListener Works on page 203. • Queuing DML operations There is a window in which a DML operation executed on the SQLFire system has not yet been placed into the internal queue of DBSynchronizer. The record is guaranteed to be placed into the internal DBSynchronizer queue only when the DML operation is completed. This restriction also applies to DML operations placed on a gateway sender queue for WAN replication. • Case-insensitive identifiers required If your third-party database provides an option for using case-sensitive SQL identifiers, you must configure the database to use case-insensitive identifiers. For example, if you use MySQL as a backend database you must set the lower_case_table_name server system variable to 1. See lower_case_table_names in the MySQL documentation for more information. Per the SQL-99 standard, DBSynchronizer treats identifiers as insensitive unless they are delimited in quotes. Specifically, DBSynchronizer converts identifiers to uppercase characters for INSERT operations (but not DELETE operations), so the backend database must be compliant with case-insensitive identifiers. • Auto-generated key configuration If cached tables require automatic generation of identity column values, then you should use SQLFire to automatically generate the key values but disable generated keys in the backend database. See Considerations for Auto-Generated Keys on page 191. Configuring DBSynchronizer You install and configure DBSynchronizer similar to the way you would install any other AsyncEventListener implementation, using the CREATE ASYNCEVENTLISTENER statement. However, DBSynchronizer requires initialization attributes to establish a connection with a third-party database. Prerequisites Preconfigure the third-party database with the schema and table definitions using the same names as those used in the SQLFire database. When you deploy DBSynchronizer, you specify an initialization String of the form DRIVER_CLASS_NAME,DB_URL. DRIVER_CLASS_NAME is the name of the JDBC driver for the third-party database (the class that implements java.sql.Driver). DB_URL is the full JDBC connection string to use to connect to the third-party database. Include any required connection parameters, such as user credentials, database names, and so forth, in the URL. DBSynchronizer uses the string to obtain a java.sql.Connection to the third party RDBMS. Procedure The following procedure describes how to configure SQLFire with DBSynchronizer to apply table DML operations to a third-party database. Note: The example commands in this procedure use MySQL Community Server 5.5.18 as the third-party database with the Connector/J 5.1.18 driver. However, the general steps are the same regardless of which database you use. Consult your third-party database and JDBC driver documentation for more information. 211 Caching Data with vFabric SQLFire Note: If you are synchronizing tables in a MySQL database, you must configure MySQL to use case-insensitive identifiers. See Restrictions and Limitations on page 210. 1. Configure the third-party database Before you configure DBSynchronizer in SQLFire, install and configure the third-party database. Create the database schema and table definitions for all of the tables that you intend to use in SQLFire. To ensure that the tables stay in synch with those in SQLFire, only create the table definitions in the third-party database. Insert and update rows only in SQLFire, so that DBSynchronizer can apply your changes to the database. For example, begin by starting MySQL if it is not already running: sudo mysqld_safe In a separate terminal prompt, start the mysql client and create a new database and table definition. Log on using an account that has privileges to create a new database. For example: mysql -u my_username -p mysql> create database sqlfdb; mysql> use sqlfdb; mysql> create table sqlftest -> (id int not null, name varchar(10)); You will create a table of the same name, "sqlftest," in SQLFire, and associate it with a DBSynchronizer. 2. Configure JDBC connectivity to the third-party database DBSynchronizer requires a JDBC driver and connection URL to connect to the third-party database and apply DML operations. Before you configure DBSynchronizer, use a Java client application such as SQuirreL SQL to verify that you can connect to the database. In the MySQL example shown in this procedure, the components necessary to establish a JDBC connection are: • Driver JAR file: mysql-connector-java-5.1.18-bin.jar • Driver class: com.mysql.jdbc.Driver • Connection URL: jdbc:mysql://localhost:3306/sqlfdb?user=sqlfuser&password=sqlfpassword Note: Although you can include the username and password directly in the JDBC connection URL (as shown above), doing so runs the risk of having the plain-text password appear in exception messages. To avoid recording plain-text passwords, this example will use an encrypted secret generated using the sqlf encrypt-password command. To ensure that SQLFire can access the JDBC driver class, add the JAR location to your CLASSPATH. For example, open a new command prompt and enter: export CLASSPATH=$CLASSPATH:/path/mysql-connector-java-5.1.18-bin.jar 3. Start a SQLFire data store in a custom server group When you create a new AsyncEventListener such as DBSynchronizer, you must assign the listener to an available server group. For example, to start a SQLFire data store and add it to a named server group: mkdir sqlfdbsync cd sqlfdbsync export CLASSPATH=$CLASSPATH:/path/mysql-connector-java-5.1.18-bin.jar sqlf server start -server-groups=dbsync This starts a new SQLFire data store server and assigns it to the "dbsync" server group. 212 vFabric SQLFire User's Guide Using DBSynchronizer to Apply DML to an RDBMS 4. Encrypt the Database Credentials Use the sqlf encrypt-password command with the external option to encrypt the database credentials: sqlf encrypt-password external Enter User Name: sqlfuser Enter password: sqlfpassword Re-enter password: sqlfpassword Connecting to distributed system: mcast=/239.192.81.1:10334 Encrypted to 25325ffc3345be8888eda8156bd1c313 You will use the encrypted secret when configuring the DBSynchronizer initialization parameters, so that the plain-text password never appears in exception messages. The above example uses the default AES transformation and 128-bit key size for encryption. See sqlf encrypt-password on page 385 for information about changing those options. 5. Create the AsyncEventListener configuration Connect to SQLFire and create a new AsyncEventListener using the DBSynchronizer. Ensure that you have added the third-party JDBC driver JAR file to your classpath, then start sqlf and create the listener definition: export CLASSPATH=$CLASSPATH:/path/mysql-connector-java-5.1.18-bin.jar sqlf sqlf> connect client 'localhost:1527'; sqlf> create asynceventlistener testlistener > ( > listenerclass 'com.vmware.sqlfire.callbacks.DBSynchronizer' > initparams > 'com.mysql.jdbc.Driver,jdbc:mysql://localhost:3306/sqlfdb,user=sqlfuser,secret=25325ffc3345be8888eda8156bd1c313' > ) > server groups (dbsync); The LISTENERCLASS argument must specify the built-in SQLFire DBSynchronizer implementation. The INITPARAMS argument must specify the full JDBC driver class name to use and the JDBC connection string, separated by a comma. Notice that the INITPARAMS also includes the username and secret options to specify the encrypted password of the user, rather than the plain-text password. Note: You can optionally install and start the AsyncEventListener configuration after you associate a table with the listener name. Make sure that you use the same listener name with both the CREATE ASYNCEVENTLISTNER command and the CREATE TABLE command. 6. Start the AsyncEventListener Use the SYS.START_ASYNC_EVENT_LISTENER procedure to start the new DBSynchronizer implementation: sqlf> call sys.start_async_event_listener('TESTLISTENER'); Note: The AsyncEventListener name is a SQL identifier and should be entered in uppercase letters with this procedure. 7. Create identical schema and tables in SQLFire After you create the DBSynchronizer listener in SQLFire, create tables and associate them with the listener to have DBSynchronizer propagate subsequent table DML operations to the third-party database. The tables 213 Caching Data with vFabric SQLFire you create should use the same schema, table name, and table definitions as those you used in the third-party database. For example: sqlf> create schema sqlfdb; sqlf> set schema sqlfdb; sqlf> create table sqlftest > (id int not null, name varchar(10)) > asynceventlistener(testlistener); Notice that the table definition is the same as that used in MySQL, except that includes the ASYNCEVENTLISTENER clause to associate the table with DBSynchronizer. Note: Because the associated listener configuration does not have to be available at the time you create the table, SQLFire does not display an error message if the specified listener name does not yet exist. Make sure that you use the same listener name with both the CREATE ASYNCEVENTLISTNER command and the CREATE TABLE command. 8. Execute DML and verify synchronization After you associate the table with a DBSynchronizer implementation, SQLFire queues DML operations that are executed against the table to the third-party database specified in the DBSynchronizer INITPARAMS argument. For example, while still in sqlf, execute: sqlf> insert into sqlftest values (1, '1st Entry'); Then return to the mysql client and verify that the DML was propagated to your database: mysql> select * from sqlfdb.sqlftest; 214 vFabric SQLFire User's Guide Chapter 36 Suppressing Event Callbacks for a vFabric SQLFire Connection When you manage a cached RDBMS with SQLFire, you may occasionally need to modify table data without triggering a configured AsyncEventListener (including DBSynchronizer) or cache plug-in implementation. SQLFire provides the skip-listeners connection property to disable DML event propagation for a particular connection to the SQLFire cluster. You can use the skip-listeners property with either a peer client or a thin client connection. When you set the property to "true," SQLFire does not send DML events that are generated by the connection to a configured DBSynchronizer, AsyncEventListener, or cache plug-in (writer or listener) implementation. Note: Setting this property to true does not affect WAN replication using a configured gateway sender. SQLFire always propagates DML operations to an enabled WAN site. For example: Properties props = new Properties(); props.put("skip-listeners","true"); final Connection conn = DriverManager.getConnection("jdbc:sqlfire:", props); Or, adding the property directly to the connection string: final Connection conn = DriverManager.getConnection("jdbc:sqlfire:;skip-listeners=true"); 215 Part 7 Deploying vFabric SQLFire Deploying vFabric SQLFire describes how plan the organization of SQLFire distributed members, and how to configure and start SQLFire servers and locators from the command line. Deploying vFabric SQLFire also explains how to configure a vFabric SQLFire Enterprise installation for replication across a Wide Area Network (WAN). Topics: • • • • • • SQLFire Deployment Models Steps to Plan and Configure a Deployment Configuring Discovery Mechanisms Starting and Configuring SQLFire Servers Configuring Multi-site (WAN) Deployments Configuring Authentication and Authorization 217 Chapter 37 SQLFire Deployment Models Choose a SQLFire deployment model based on your network topology, performance, and data volume requirements. SQLFire supports three basic types of deployment: client/server, embedded peer-to-peer, and multi-site (WAN). You can also deploy SQLFire using elements from each topology. For example, embedded SQLFire members can join an existing cluster of SQLFire servers. Both embedded cluster and client-server topologies can use WAN replication as necessary. 219 Deploying vFabric SQLFire Embedded Peer-to-Peer Deployment The embedded, peer-to-peer distributed system (also known as an embedded cluster) is the building block for all vFabric SQLFire installations. With an embedded cluster, the core SQLFire engine is embedded alongside an existing Java application in the same JVM. When the application initiates a connection to SQLFire using the peer JDBC driver, it starts a SQLFire peer member that joins other peers in the same cluster. • Understanding Embedded Peer-to-Peer Deployment on page 220 • Deciding When to Use Embedded Peer-to-Peer on page 220 • Example Code for Embedding SQLFire Members on page 221 Understanding Embedded Peer-to-Peer Deployment The embedded peer-to-peer model provides embedded Java applications with default one-hop or no-hop access to data. Each peer member communicates directly with the other members of the cluster and can host data as necessary, persist data to disk (if it is a data store), and participate in distributed queries. All peers are treated as "fully authorized" by the SQLFire security framework after they are authenticated. An embedded SQLFire peer can optionally provide network server functionality for applications that need to support connectivity from JDBC or ADO.NET clients. Or, you can embed SQLFire in a cluster of application servers such as Apache Tomcat or Oracle WebLogic, which provide their own network server functionality. A single attribute in the JDBC peer driver connection determines whether the SQLFire peer also provides network services. Embedding SQLFire peer services is supported only for Java applications. Existing Java applications can easily switch to using an embedded SQLFire peer by including the required SQLFire libraries and specifying the SQLFire JDBC peer client URL. Note: In this release of SQLFire, ADO.NET clients cannot connect as peers. Deciding When to Use Embedded Peer-to-Peer Here are typical scenarios in which you would use the embedded peer-to-peer model: • Many applications frequently accessing content directly from within the process heap (for example, session state data or other Web content). The embedded peer-to-peer model automatically provides one-hop or no-hop access to data. The SQLFire JDBC thin-client driver also supports one-hop access for lightweight client applications. • More convenient from an administration and management standpoint. With an embedded cluster, there is no need to manage any external processes in order to deploy SQLFire peers. For example, if you embed SQLFire in a cluster of Java application servers, each application server and the associated SQLFire peer share the same process heap. • Applications requiring a few peer clients (as opposed to hundreds). Deploying many peers increases the buffering and socket overhead for each member. Having numerous peers can also strain the group membership system coordinator, and it increases the overhead necessary for detecting failures. In an embedded cluster deployment, all SQLFire transactions and distributed locks are maintained by the peers themselves. This is in contrast to the client-server deployment model, in which clients are required to execute server-side code (such as stored procedures) in order to acquire locks or execute transactions. • Partitioned caching applications in which a small number of "feed" clients push data to an RDBMS at a very fast rate. This scenario is particularly suited to embedded peer-to-peer. SQLFire peer members dispatch messages to other peers synchronously by default, and with minimal context-switching. This provides the lowest possible latency and offers the highest distribution throughput for both replicated caching as well as partitioned caching applications. It also offers the lowest distribution latency, which useful for latency-sensitive "feed" clients. 220 vFabric SQLFire User's Guide SQLFire Deployment Models Other (non-"feed") clients should connect to the distributed cache cluster as non-peers (see SQLFire Cache Strategies on page 191). Note: In a partitioned caching application, updates to distributed data are synchronously or asynchronously propagated to a backend database server using the SQLFire caching framework (see SQLFire Cache Strategies on page 191). Example Code for Embedding SQLFire Members If your application embeds a SQLFire member of any type (a peer client, server, or locator), you should use the FabricServiceManager API to embed the required type. The application should embed SQLFire in the main thread before any other thread attempts to connect to the cluster. Starting SQLFire Servers with the FabricServer Interface on page 119 summarizes the steps involved in using the FabricServiceManager API. For example, to embed a SQLFire locator inside an application: Properties props = new Properties(); // add desired properties if required. FabricLocator locator = FabricServiceManager.getFabricLocatorInstance(); locator.start("localhost", 22343, props); A second application could use the above locator for discover. This example code connects using a locator, and also adds the embedded SQLFire member to server groups "sg1" and "sg2:" Properties props = new Properties(); // add desired properties if required. props.setProperty("server-groups", "sg1,sg2"); props.setProperty("locators", "localhost[22343]"); props.setProperty("host-data", "true"); // not required as the default // is true FabricServer server = FabricServiceManager.getFabricServerInstance(); server.start(props); 221 Deploying vFabric SQLFire In some cases you may want to embed a SQLFire accessor. This is a SQLFire member that does not host data, but otherwise participates in the cluster. This code starts an accessor and also uses the locator for discovery: Properties props = new Properties(); // add desired properties if required. props.setProperty("server-groups", "sg3"); props.setProperty("locators", "localhost[22343]"); props.setProperty("host-data", "false"); FabricServer server = FabricServiceManager.getFabricServerInstance(); server.start(props); After starting a peer client, locator, or accessor as above, an application can obtain a connection: String embedConnURL = "jdbc:sqlfire:"; Properties connProps = new Properties(); connProps.setProperty("user", "tom"); connProps.setProperty("password", "tomspassword"); Connection conn = DriverManager.getConnection(embedConnURL, connProps); // create a table using this connection Statement s = conn.createStatement(); st.execute("create table customer (id int not null, name varchar(100) not null"); Client-Server Deployment In an environment where hundreds or thousands of application clients need access to data, it is impractical for all clients to be members of a single distributed system, connected to each other, as with embedded peer-to-peer. To support many clients, you can deploy SQLFire as a cluster of standalone server processes (called SQLFire servers). • Understanding Client-Server Deployment on page 222 • Deciding When to Use the Client-Server Model on page 222 Understanding Client-Server Deployment Each SQLFire server runs in its own process and provides network server functionality to manage connections to clients and other servers in the cluster. Although each SQLFire server runs in a standalone process, all servers become part of a single distributed system with direct connectivity to each other. In the client-server deployment model, the client driver is lightweight (less than 1MB) and is implemented as a thin JDBC driver for Java applications, or as an ADO.NET for Microsoft .NET and Mono applications. In contrast to the SQLFire peer JDBC driver, the JDBC thin driver and ADO.NET driver only provide connectivity to an existing cluster of SQLFire servers or peer client members. Thin clients do not host or persist cluster data, and they do not directly participate in distributed queries that execute in the cluster. Thin clients initially connect to only one server at a time. Multiple thin-client connections can be load-balanced across all SQLFire servers in the cluster. After establishing a connection to a cluster, JDBC thin-clients have the ability to directly access multiple SQLFire members when executing queries. This provides single-hop access to data in the cluster for lightweight client applications. Deciding When to Use the Client-Server Model Unlike the embedded peer-to-peer model that supports only Java applications, the client-server deployment model allows Java, Microsoft .NET, and Mono applications to access SQLFire. Here are typical scenarios in which you would use the client-server model rather than embedded peer-to-peer: 222 vFabric SQLFire User's Guide SQLFire Deployment Models • When you must support numerous clients, and scalability is a more important factor than distribution latency. • When the clients have a short life span. It may be desirable to keep the clients separated from the data stores (peers or servers). If peer clients continually attach to an embedded cluster, the overhead of re-creating data from disk or another repository becomes too expensive, and a client-server deployment should be considered instead. • When clients reside on desktop computers or connect over a remote network. Peer connectivity between clients may be impossible or undesirable because of firewalls and other network boundaries. Multi-site Deployment Both embedded peer-to-peer clusters and SQLFire server clusters are tightly-coupled by design. When members of a SQLFire cluster must share data with each other, scalability problems are magnified if the members span multiple networks that are spread out geographically across a WAN. To address this issue, SQLFire extends the client-server deployment model by providing highly-available gateways that replicate data to remote clusters in a hub-spoke model. • Understanding Multi-site Deployment on page 223 • Deciding When to Use Multi-site Deployment on page 223 Understanding Multi-site Deployment The vFabric SQLFire multi-site implementation loosely couples individual SQLFire distributed systems by using gateways. A gateway is a logical connection between systems that replicates DML operations for configured tables. The gateway between systems is tolerant of weak or slow physical connections between distributed system sites. All data exchange occurs asynchronously without any loss of data or loss of event ordering. Although the figure above shows only two SQLFire clusters joined by a gateway, you can daisy-chain multiple distributed systems simply by adding more gateways to your deployment. Deciding When to Use Multi-site Deployment A wide-area network (WAN) is the main use case for the multi-site topology. The multi-site topology enables systems at disparate geographical locations to replicate DML operations for configured tables and provide a coherent view of the tables' data. It also ensures independence of the systems, so if any are lost from view, the remaining systems continue to operate. The WAN model is generally deployed either for data visibility across multiple data centers, or as a mechanism for disaster recovery. Client applications can connect to the SQLFire cluster in the local data center, but if 223 Deploying vFabric SQLFire visibility to the cluster is lost, then those clients can fail over to any other cluster that replicates data using a gateway. A multi-site deployment requires a vFabric SQLFire Enterprise license for each data host in each site. How Multi-site Systems Work Each distributed system in a multi-site configuration operates independently of the other connected systems. Each system can be configured as necessary for the resources available at the local site, as well as the local topology (peer-to-peer and/or client-server). However, tables that are configured for replication between sites must be created using identical table names and column definitions. In addition, gateway senders and receivers must be configured to assign logical gateway connections to physical network connections in each system. For each table that is configured to use a gateway sender, DML events are automatically forwarded to the gateway sender for distribution to other sites. The events are placed in a gateway queue and distributed asynchronously to remote sites. The ordering of events sent between sites is preserved. The following types of DML operations are distributed: • inserts • updates • deletes (except for data deletion associated with table expiration). Other operations are not distributed, such as: • Queries against the table • DDL operations of any kind • Expiration actions of any kind • Transaction boundaries that involve the configured table If the queue of DML events becomes too full, it is overflowed to a disk store to keep the member from running out of memory. Optionally, you can configure the queue to be persisted to disk. With persistence, if the member that manages the queue goes down, the member picks up where it left off after it is restarted. How Multi-site Event Distribution Works In a multi-site configuration, vFabric SQLFire distributes table DML operations between remote distributed systems, with a minimum impact on each system's performance. DML events are distributed only for the tables that you configure for replication by using a gateway receiver. The DML event contains the originating site's distributed system ID, and the ID of each site to which it sends the event. This information ensures that no site re-forwards the event to a site that has already received the event. When a SQLFire site receives an event for a table DML operation, it forwards the event to the other sites it knows about (sites that correspond to configured gateway senders for the table), but it excludes those sites that it knows have already received the event for the table. Note: A DML event does not record the ID of the sites that receive and apply the DML event. This means that unsupported WAN topologies can result in more than one copy of an event being applied to a single site. This can lead to duplicate data or failed DML execution in the table, and must be avoided. See the discussion of supported and unsupported topologies under Supported and Unsupported Topologies on page 225. • How a Gateway Processes Its Queue on page 224 • How a Gateway Handles Batch Processing Failure on page 225 How a Gateway Processes Its Queue Each primary gateway sender contains a processor thread that reads messages from its queue, batches them, and distributes them to the connected site. To process the queue, the thread takes the following actions: 224 vFabric SQLFire User's Guide SQLFire Deployment Models 1. 2. 3. 4. Reads messages from the queue. Creates a batch of the messages. Synchronously distributes the batch to the remote site and waits for a reply. Removes the batch from the queue after the remote site has successfully replied. Because the batch is not removed from the queue until after the remote site has replied, the message cannot get lost. However, this also means that a message can be processed more than once in certain failure scenarios. If a site goes offline in the middle of processing a batch of messages, that same batch is sent again after the site is back online. See About High Availability for WAN Deployments on page 239. The batch is configurable via the batch size and batch time interval settings, which you can specify when you create a gateway sender (see CREATE GATEWAYSENDER on page 498). A batch of messages is processed by the queue when either the batch size or the time interval is reached. In an active network, it is likely that the batch size will be reached before the time interval. In an idle network, the time interval will most likely be reached before the batch size. This may result in some network latency that corresponds to the time interval. How a Gateway Handles Batch Processing Failure These types of exceptions can occur during batch processing: • A gateway receiver fails with acknowledgment. If processing fails while the receiving gateway is processing a batch, it replies with a failure acknowledgment containing the exception, including the identity of the message that failed, and the ID of the last message successfully processed. The sending gateway removes the successfully processed messages and the failed message from the queue and logs the exception and the failed message information. The sender then continues processing the messages remaining in the queue. • The receiving gateway fails without acknowledgment. If the receiving gateway does not acknowledge a sent batch, the sender does not know which messages were successfully processed, so it re-sends the entire batch. • No remote gateways are available. If a batch processing exception occurs because no remote gateways are available, the batch remains on the queue. The sending gateway waits for a time, then attempts to re-send the batch. The time periods between attempts is five seconds. The existing server monitor continuously attempts to connect to the remote gateway, so eventually a connection is made and queue processing continues. Messages build up in the queue and possibly overflow to disk in the meantime. Supported and Unsupported Topologies Make sure you use a supported multi-site topology and understand why invalid topologies can lead to data inconsistency. • Supported Topologies on page 225 • Unsupported Topologies on page 226 See also Limitations of Multi-Site Replication on page 240. Supported Topologies SQLFire supports WAN topologies that use gateways to connect each individual distributed system to each other distributed system in the WAN. This parallel network topology is a robust configuration in which any one of the sites can go down without disrupting communication between the remaining sites. This configuration also guarantees that no site receives multiple copies of the same DML operation. The parallel topology for three sites is shown in the following figure. In this scenario, a DML operation originating in any site is distributed to the remaining two sites, and neither site forwards the event further. If any site is removed, the other two maintain a parallel topology. 225 Deploying vFabric SQLFire An example sequence of event routing: 1. A configured table in Site 1 is updated. 2. Site 1 distributes a DML event to both Site 2 and Site 3. The DML event lists Site 1 as the originator, and sites 2 and 3 as the destinations. 3. Site 2 receives and applies the DML event. Although Site 2 is configured to replicate table DML operations to Site 3, the DML event indicates that Site 3 is already a destination for the DML operation, so it does not forward the event to Site 3. 4. Site 3 receives and applies the DML event. Although Site 3 is configured to replicate table DML operations to Site 2, the DML event indicates that Site 2 is already a destination for the DML operation, so it does not forward the event to Site 2. In other words the parallel topology ensures that under normal operating conditions, a DML operation at any one site is applied once and only once to every other connected site in the WAN. Unsupported Topologies Any topology in which one or more of the configured WAN sites does not contain a gateway to every other WAN site can lead to a variety of problems, and is unsupported. The most significant problem occurs when sites are configured so that one or more sites receive multiple copies of the same DML event. For example, in the following unsupported configuration causes site 4 to apply the same DML event multiple times. The sequence of event routing is: 1. A configured table in Site 1 is updated. 2. Site 1 distributes a DML event to both Site 2 and Site 3. The DML event lists Site 1 as the originator, and sites 2 and 3 as the destinations. 3. Site 2 receives and applies the DML event. However, it is configured to distribute DML operations for the table to Site 4. Because the DML event from Site 1 does not list Site 4 as a destination, it forwards the event to Site 4. The DML event lists Site 2 as the originator and Site 4 as the destination. 4. Site 3 receives and applies the DML event. However, it is also configured to distribute DML operations for the table to Site 4. Because the DML event from Site 1 does not list Site 4 as a destination, it also forwards the event to Site 4. The DML event lists Site 3 as the originator and Site 4 as the destination. 5. Site 4 receives the DML events sent from Sites 2 and 3. Because each event has a unique originator, there is no way to determine that both events originated from the single DML operation in Site 1. Site 4 applies both DML events, and the table now contains inconsistent data in Site 4. 226 vFabric SQLFire User's Guide Chapter 38 Steps to Plan and Configure a Deployment Work with your host system administrators to plan your overall deployment strategy. Create a detailed list of the machines and communication ports that your SQLFire peer and server members will use. Your deployment decisions determine how servers and peers find each other and distribute data in the cluster. The following steps are high-level tasks for planning and configuring your deployment. Where necessary they provide links to more detailed procedures. 1. For each host machine with more than one network adapter card, decide whether to use the default address or one or more non-default bind addresses. You can use different cards for peer and server connections. 2. Identify which SQLFire servers, if any, that you want to run as standalone, isolated members, with no membership in a cluster. Standalone servers may be sufficient for certain applications. A single server has faster startup, but no peer-to-peer distribution of any kind. 3. For all other clustered SQLFire members: • Decide whether to use locators or a multicast address for member discovery. Locators are recommended for production systems and required for implementing security, network partitioning management, and thin client load balancing. Decide how many locators to use and where each locator should run. To ensure the most stable startup and availability, use multiple locators that run on different computers. Create a list of your locators' address and port pairs. You will use the list to configure other clustered SQLFire peers or servers, thin client connections, and the locators themselves. • If you choose a multicast address for communication or as an alternative to locators for peer member discovery, record the unique multicast address and port for each separate cluster. Note: Use different port numbers for different clusters, even if you already use different multicast addresses. Some operating systems do not separate communication between systems that have unique addresses but the same port number. 4. Set up member discovery using either locators or multicast. See Configuring Discovery Mechanisms on page 229. 5. As needed, set up communication between multiple clusters. See Configuring Multi-site (WAN) Deployments on page 237. When you start SQLFire servers or peer client members, they find and communicate with each other using methods and addresses that you configure. 227 Chapter 39 Configuring Discovery Mechanisms Whether you deploy embedded SQLFire peers or standalone SQLFire servers, members of the same cluster must use a common discovery method to locate each other. UDP multicast and TCP locators are the two mechanisms supported for SQLFire member discovery. Using Locators A SQLFire locator is a process that tells new, connecting peers and thin clients how to connect to peers that are already running. Locators also load balance thin client connections to available SQLFire members in a client-server deployment. In general, run a locator as its own process (standalone), rather than running a locator process alongside the full SQLFire engine (on a peer client or a data store). Running standalone locators provides the highest reliability and availability for the locator service as a whole. Standalone locators are also required for systems that enable network partitioning management. Start and Stop Locators You start and stop locators with the sqlf utility and the locator script. The command line options determine the address and port at which SQLFire peers communicate with the locator, as well as the address and port that thin clients use to connect to the SQLFire cluster using the locator. Start Locators Always start locator members first when you start a SQLFire cluster. This ensures that the locators can manage server discovery from the beginning, as individual SQLFire servers join and leave the cluster. If your cluster uses multiple locators, specify the complete list of locator addresses and ports when you start each locator. For example, the following command starts an initial locator for both peer and client access: sqlf locator start -peer-discovery-address=locator1host -peer-discovery-port=10101 \ -locators=locator1host[ 10101],locator2host[ 20202] \ -client-bind-address=locator1host -client-port=1527 -dir=locator1 The -peer-discovery-address and -peer-discovery-port options define a unique connection that all members of this SQLFire distributed system use for communicating with the locator (see Start and Stop Locators on page 229). The -client-bind-address and -client-port options define a connection that client applications can use to connect to the cluster using this locator (see Connect to a Distributed System Using Locators on page 231). 229 Deploying vFabric SQLFire The -locators option lists the peer connection information for all locators used in the same SQLFire distributed system. The command above specifies a distributed system with two locators. The second locator would be started using a similar command: sqlf locator start -peer-discovery-address=locator2host -peer-discovery-port=20202 \ -locators=locator1host[ 10101],locator2host[ 20202] \ -client-bind-address=locator2host -client-port=1528 -dir=locator2 All log and status files are stored in the specified directories (or in the current working directory if you omit the -dir option). Configure Locators for WAN Member Discovery on page 242 provides additional information about starting locators for WAN replication. Stop Locators To stop a running locator, use the command: sqlf locator stop -dir=locator_directory To stop an entire SQLFire distributed system, always use the sqlf shut-down-all command. This command stops all data stores and accessors in the system, but leaves locators and JMX agents running. If necessary, shut down locators individually, but only after all data stores in the system have finished shutting down. Start SQLFire Peers and Servers Using Locators SQLFire peers or servers must specify a list of locator addresses to connect to when they join the distributed system. Use the -locators option when starting a SQLFire server or peer to identify the peer connection the member should use to join the distributed system. In the previous section, Start and Stop Locators on page 229, two locators were started using the -peer-discovery-address and -peer-discovery-port combinations of "locator1host:10101" and "locator2host:20202." In order to join the distributed system created by these locators, new SQLFire servers must specify those peer connections at startup. For example, to start a new SQLFire server in the same cluster defined in Start and Stop Locators on page 229, use the command: sqlf server start -locators=locator1host[ 10101],locator2host[ 20202] \ -client-bind-address=server1host -client-port=1529 -dir=server1 Any additional servers joining the same cluster would likewise specify the same list of locators: sqlf server start -locators=locator1host[ 10101],locator2host[ 20202] \ -client-bind-address=server2host -client-port=1530 -dir=server2 Embedded SQLFire peers can supply the locators attribute in the JDBC peer client connection string. For example: jdbc:sqlfire:;locators=locator1host[port1],locator2host[port2];host-data=false As each server or peer joins the distributed system, both locators update their information with the new server's client connection information. Note that although each server defines a client bind address and port, individual clients should connect directly to one of the available locators rather than to an individual server. In this way, the locator can load balance client connections to available servers, and can manage the list of available servers as they leave and join the distributed system. 230 vFabric SQLFire User's Guide Configuring Discovery Mechanisms Connect to a Distributed System Using Locators SQLFire thin clients specify the client bind address and port of a locator in order to connect to a SQLFire cluster. Connecting to a locator ensures that a client is load-balanced to an available SQLFire server in the distributed system. If the client's connection to a server is dropped (for example, if the server is shut down), then the client can retry connecting to the same locator to access another available server. Note: Thin clients do not specify the peer discovery addresses or port as do SQLFire servers and peers. For example, in an interactive sqlf session, use the connect client command and specify the client host and port number of a locator: connect client 'locator1host:1527'; In a third-party JDBC tool, specify the host and port in the JDBC connection string: jdbc:sqlfire://locator1host:1527 Locators balance client requests to all SQLFire servers available in a cluster, so multiple connection requests to the same locator may result in connections to different servers. Configure Multicast Discovery You configure multicast discovery by specifying the mcast-address and mcast-port properties. To start an embedded SQLFire peer with multicast discovery, specify the multicast address and port as options in the JDBC peer client connection URL, or in the property object that you send in the FabricServer.start() method. For example: jdbc:sqlfire:;mcast-address=address;mcast-port=port To start a SQLFire server with multicast discovery from a command prompt or terminal window, add the multicast properties directly to the sqlf command. For example: sqlf server start -mcast-address=address -mcast-port=port Note: Thin JDBC clients and ADO.NET clients do not connect to a cluster using multicast. Instead, they must specify the address and port of a single peer in the cluster. 231 Chapter 40 Starting and Configuring SQLFire Servers A SQLFire server provides connectivity for clients as well as other servers or peers in the cluster. Start and Stop SQLFire Servers Using sqlf Use the sqlf utility to start servers. You generally start a SQLFire server with the sqlf server command from a command prompt or terminal window. If you need to initialize other resources before booting SQLFire servers, you can start a server process from within a Java application with the FabricServer interface. See Starting SQLFire Servers with the FabricServer Interface on page 119 for more information about starting servers programmatically. Note: If you use peer clients in a SQLFire distributed system that also contains data stores, keep in mind that peer clients themselves cannot use disk stores to persist data. You must start data stores and locators before starting peer clients, because peer clients rely on those members to persist data. See Peer Client Considerations for Persistent Data on page 92 for more information. Start SQLFire Servers By default, the sqlf server command starts a server that can host data and provide connectivity to thin client applications. The complete syntax for starting a SQLFire server with sqlf server is: sqlf server start [-Jjvm_argument]* [-dir=working_directory] [-classpath=classpath] [-serverGroups=group1[,group2][,...]] [-maxHeap=size] [-initialHeap=size] [-run-netserver=true|false] [-rebalance] [-configScripts=sql-files] [-initScripts=sql-files] [-client-bind-address=client_address] [-client-port=port] [-critical-heap-percentage=] [-mcast-port= (default 10334)] [-mcast-address=
(default 239.192.81.1)] [-locators=] [-start-locator=
] [-host-data= (default true)] [-auth-provider=] [-server-auth-provider=] [-user=] [-password[=]] 233 Deploying vFabric SQLFire [-log-file= (default sqlfserver.log)] [-property_name=property_value]* The sqlf server command uses default values for any options that you do not specify on the command line. However in most cases you will want to specify non-default values for each server that you start. The sections that follow describe some of the most commonly-used options and configuration properties. Stop SQLFire Servers You can use two additional command forms to stop a running SQLFire server or display the status and process ID of a running server: sqlf server stop [-dir=working_directory] sqlf server status [-dir=working_directory] Specify the Server Working Directory As a best practice, create a dedicated directory for each server that stores SQLFire log and status files. Both the sqlf server command and FabricServer interface use a working directory to read input configuration files and to write log files, disk store files, and the server status file. By default, a new SQLFire server reads or creates files in the directory from which you run the sqlf server command or execute the FabricServer.start method (the server working directory). As a best practice, create a dedicated directory for each server and specify the working directory for the server at startup using the dir option at boot time. For example: mkdir server1 sqlf server start -dir=./server1 Input configuration properties can be defined in a properties file, specified as command-line options to the sqlf server command, or specified as Java system properties using the -property_name=property_value syntax. You can also rely on default property values for many aspects of the configuration. SQLFire uses different conventions for defining properties in each location. See Configuration Properties on page 327. Specify Client Connection Information You need to specify thin client connection properties to avoid port conflicts at boot time. By default, the SQLFire server that you start with the sqlf server command supports connectivity to thin client applications over a unique bind address and port number combination. If you do not specify an address and port, the server binds to the default address (usually localhost) on port 1527. Because each server must bind to a unique address and port combination, you should specify the exact client connection properties to use at boot time to avoid port conflicts. For example: sqlf server start -dir=./server1 -client-bind-address=localhost -client-port=1528 As an alternative, you can disable network services if you do not need to support thin client connections to the server: sqlf server start -dir=./server1 -run-netserver=false Define Server Groups Each server that you start with the sqlf server command is configured to host data by default and is automatically added to the default server group. As you create partitioned or replicated tables in your cluster, you will also want to configure servers to participate in different server groups to control where table data is distributed. 234 vFabric SQLFire User's Guide Starting and Configuring SQLFire Servers Server groups enable you to logically group SQLFire peers and servers for managing table data. When you start an SQLFire server, you specify one or more server group names for the server using the -server-groups option. For example: sqlf server start -dir=./server1 -server-groups=servergroup1,servergroup2 If you use the FabricServer interface in a Java application, specify the server-groups boot property when you start the server. After starting servers in multiple server groups, you can specify the target groups for partitioned or replicated tables in the CREATE TABLE statement for those tables. See Server Groups Overview on page 63. Execute SQL When You Start a Server You can configure a SQLFire server or peer to execute SQL scripts during its boot process. You can also use configuration and initialization scripts as an alternative to data dictionary persistence. You specify SQL scripts using the following startup arguments, which determine when the server executes the script: • -config-scripts argument to the sqlf server command, or the config-sql-scripts connection property with the FabricServer interface. Configuration scripts are executed early in the server boot process, before SQLFire executes DDL from other peers and servers and before it loads any persistent data from disk. Use configuration scripts for any preboot configuration that might affect later DDL execution. • -init-scripts argument to the sqlf server command, or the init-sql-scripts connection property with the FabricServer interface. Initialization scripts are executed after the initial DDL execution, during the boot procedure. Use initialization scripts to load data into existing tables or to execute DDL statements that depend on other DDL statements delivered from other peers or servers. To use configuration and initialization scripts as an alternative to data dictionary persistence, ensure that the first peer or server that you start in the cluster uses configuration scripts to execute the required DDL for your application. All other peers and servers can then use initialization scripts to finish executing dependent DDL and to populate your schema with data. Using Additional Boot Properties The sqlf server command uses command-line arguments to configure most boot properties for SQLFire servers. You can specify a number of additional SQLFire properties to configure different aspects of the distributed system. You pass additional properties to the script as "-key=value" pairs on the command line, where the key corresponds to a valid SQLFire property. Or, you can define parameter values in a properties file that the sqlf server command reads at runtime. By default, the server reads input configuration properties from a file named sqlfire.properties in the working directory. You can specify a different configuration file by using the sqlfire.properties property at boot time. You can use supported configuration properties either with the sqlf server command or the FabricServer interface in Java applications. You can also specify the properties as JDBC connection properties when you start a peer client using the JDBC peer driver as described in Developing Java Clients and Peers on page 123. Configuration Properties on page 327 describes all available configuration properties. Configuring SQLFire Properties SQLFire uses property values to configure the behavior of the distributed system. You can specify property values in a variety of ways depending on how you start the SQLFire server or peer. Precedence for Using Property Values SQLFire configuration attribute values can come from the following sources: 235 Deploying vFabric SQLFire 1. System properties If a system property named sqlfire. is defined and its value is not an empty string, then its value will be used for the named configuration attribute. 2. Connection properties Properties can be passed in a Properties object passed to the DriverManager.getConnection method. 3. File properties Otherwise, if a property is defined in a Specifying a Property File on page 236 found by this application, and its value is not an empty string, then its value will be used for that attribute. 4. Defaults Otherwise a default value is used. Specifying a Property File When running the interactive sqlf tool, you can specify the location of the properties file using the -p propertyfile option on the command line when you start sqlf. The name of a property file can be optionally specified using the sqlfire.properties system property. If the system property is set to an absolute file name then that file is used as the property file. If the system property is set to a relative file name then it is searched for in the below locations. If the system property is not set, then the name of the property file defaults to sqlfire.properties and is searched for in the following locations: 1. Current directory (directory in which the process was launched) 2. User's home directory 3. Class path (loaded as a system resource) Persisting the Data Dictionary By default, SQLFire persists the data dictionary for any data store member (members that use the host-data=true boot property). When persistence is enabled for a SQLFire member, the member preserves all table, index, trigger, and procedure definitions in a disk store, even when all members of the distributed system are down. When the system is brought back up, there is no need to re-execute the data definition statements (DDL). Persistence of the data dictionary is controlled by the persist-dd boot property. By default, this property is set to true for all members that host data. You must specify a consistent persist-dd value for all data stores in the same SQLFire cluster. You cannot enable persistence for SQLFire accessors in a cluster. The data dictionary is always replicated and available on each peer member of the distributed system. So, even if data dictionary persistence is turned off, the dictionary is preserved as long as there is at least one member of the distributed system running. If all members are brought down when persistence is turned off, you must re-execute the DDL to restore your database. The persistent data is written to a disk store the directory specified by the connection property sys-disk-dir . Each member must specify its own unique directory. When a member is brought up, it looks to other members for data before reading its persistent files. That is, live data overrides persistent data. Optimizing Availability and Performance on page 93 provides more informationa bout starting and shutting down SQLFire clusters that utilize disk stores for persistence. 236 vFabric SQLFire User's Guide Chapter 41 Configuring Multi-site (WAN) Deployments SQLFire supports propagating create, read, update, and delete operations across multiple distributed systems. You can use this feature to keep multiple clusters in synch with each other over a wide area network. Note: DDL operations and procedure execution are not propagated across WAN boundaries. See Multi-site Deployment on page 223 for more information. About Gateways A multi-site installation consists of two or more distributed systems. Each site is its own distributed system and has one or more logical connections to other sites, called gateways. • Gateway Configuration Overview on page 238 • How Gateway Sender Startup Policy Affects Startup Behavior on page 239 Configuration Diagrams In a simple multi-site deployment, two SQLFire clusters replicate DML operations to each other. If one of the SQLFire clusters fails or is taken offline for maintenance, clients in that geographical region can use the available SQLFire cluster for continued access. Figure 4: Basic WAN replication configuration More complex multi-site configurations can add additional SQLFire clusters to the basic configuration shown above. As additional clusters are added, each individual cluster in the deployment requires an additional gateway sender to ensure that each site replicates to all other sites across the WAN. (See Supported and Unsupported Topologies on page 225) 237 Deploying vFabric SQLFire For example, the following figure shows three-site WAN configuration. Each cluster uses two gateway senders to replicate DML operations to the other clusters in the system. Figure 5: WAN configuration with multiple gateway senders Gateway Configuration Overview The logical connections between distinct SQLFire clusters are known as gateways. Gateways are configured in one or more SQLFire data store members and consist of two physical connections: a gateway sender and a gateway receiver. A gateway receiver provides a physical connection for receiving DML operations from one or more remote SQLFire clusters for replicating those operations in the local cluster. Each SQLFire cluster needs only a single named gateway receiver to replicate data from all other remote sites. Remote gateway senders use any available gateway receiver to send DML operations. However, you can deploy a gateway receiver to multiple SQLFire members for high availability. A gateway sender runs on a SQLFire data store members, and it replicates configured table DML operations to another SQLFire distributed system. Each sender is usually hosted by more than one data store member, with one member hosting the primary gateway sender instance and the others hosting backup instances. The primary is the only instance that communicates with remote sites at a given time. Gateway senders are identified within the distributed system by a unique identifier. 238 vFabric SQLFire User's Guide Configuring Multi-site (WAN) Deployments Each gateway sender defines: • A unique identifier • The remote distributed system ID where the sender forwards DML operations. • The server group(s) on which to deploy gateway sender instances. • Optional variables to control the connection, persistence, and startup behavior for the sender and its queue. Notice that each gateway sender only specifies the remote distributed system ID to use for replicating DML operations. The actual connection information (the host and port number of a gateway receiver in the remote distribute system) are obtained dynamically from the cluster locators. Locators automatically update this information as gateway receivers in remote sites change or go offline. How Gateway Sender Startup Policy Affects Startup Behavior This applies to systems where a gateway sender is installed to multiple data store members. When a gateway sender is deployed to multiple data stores, only one primary sender is active at any given time. All other gateway sender instances are secondaries that act as backups to the primary. SQLFire designates the first gateway sender to start up as the primary sender, and all other senders become secondaries. As gateway senders are started and shut-down in the distributed system, SQLFire ensures that the oldest running gateway sender operates as the primary. About High Availability for WAN Deployments You can deploy a gateway sender to multiple data stores to provide high availability. At any given time, only one member has an active gateway sender process, called the primary sender, for propagating DML to a remote WAN site. All other gateway senders of the same name are treated as secondary senders. Secondary senders remain in standby mode for redundancy, to guarantee replication to the remote WAN site if the member with the primary sender fails. A SQLFire cluster needs only a single gateway receiver to receive DML events from remote distributed systems. However, as with gateway senders, you can deploy multiple instances of the gateway receiver to different SQLFire members for high availability. Gateway senders can also be configured to use an available disk store to persist queued DML operations that need to be replicated to a remote cluster. Using a disk store ensures that queued DML operations are not lost, even if you shut down the SQLFire member that hosts the primary sender. 239 Deploying vFabric SQLFire Configuring for Consistency and Redundancy To ensure high availability and reliable delivery of DML events, configure each gateway sender for both persistence and redundancy. For performance reasons, deploy no more than one secondary gateway sender (redundancy of one). If a peer or server joins an existing WAN-enabled distributed system, then WAN components, such as gateway senders and gateway receivers, are automatically created as part of DDL replay. This replay is subject to each new SQLFire member satisfying the criteria of the server group. For example, if you deploy a gateway receiver to a particular server group, and you later add a member to that server group, the receiver will be created on the new member as well. Possible Side Effect of Failover Process A side effect of the gateway sender failover process is that a DML operation may be reapplied to the remote WAN site if the primary sender fails. If the member that hosts the primary sender fails while sending a batch of operations, some DML statements in the batch may have already been applied to the remote WAN site. After a failover, the new primary sender sends the failed batch in its entirety, and reapplies the initial DML operations. Because of this, the remote WAN site may become out-of-synch depending upon the nature of the DML operation; how the DML modifies table columns; and the presence or absence of column constraints on the target table. For example, consider the following update statement: update trade.networth set availloan=availloan-? where cid = ? and tid= ? If a failure occurs mid-way through applying this DML statement, reapplying the statement decreases the "availloan" value twice in rows that applied the update before the failure. Limitations of Multi-Site Replication The vFabric SQLFire multi-site implementation has the following limitations and restrictions. • Only SQL insert, update, and delete operations are distributed using configured gateway senders. Queries and DDL operations are not distributed to remote SQLFire systems. • Table expiration actions are not distributed to remote SQLFire systems. • SQLFire does not extend transaction boundaries to remote systems that are configured for WAN replication. If you use a transaction to update a table that is configured for WAN replication, the transaction is only honored within the local SQLFire cluster where you initiated the transaction. Any DML operations that are replicated to a remote table are applied outside of a transaction • SQLFire provides no conflict detection to address simultaneous updates to table data on multiple SQLFire systems. If multiple sites in a WAN configuration update the same table data at the same time, then the table data can become inconsistent between sites. For example, consider a situation where two SQLFire sites replicate the table "employees" to each other over a WAN, and the employees data is currently consistent between both sites. Site 1 executes the DML operation: update employees set bonus = bonus + 500 where department = 'sales' At the same time, Site 2 executes the DML operation, moving the employee with ID 12345 from the Sales department to the QA department: update employees set department = 'qa' where employee_id = '12345' In this case the DML is successfully applied to each SQLFire site and propagated to the other. However, in Site 1, the employees row for employee_id 12345 has a higher bonus value than the same row in Site 2. Similar problems can occur if each site tries to add a row using the same primary key, if one site deletes a parent row required by an insert on the other site, and so forth. To avoid these kinds of inconsistencies, enable WAN replication only for tables that do not require simultaneous updates of the data on different SQLFire systems. 240 vFabric SQLFire User's Guide Configuring Multi-site (WAN) Deployments • SQLFire preserves the order of DML statements applied to the distributed system (and queued to remote WAN sites) only for a single thread of execution. See No Ordering Guarantee for DML in Separate Threads on page 156. See also the vFabric SQLFire Release Notes for information about known issues associated with multi-site deployments. Prerequisites for WAN Replication Note the prerequisites for configuring and using replication between two SQLFire clusters. To use WAN replication between multiple SQLFire clusters: • Each SQLFire distributed system that participates in WAN replication must use one or more locators for member discovery. WAN replication is not supported with multicast discovery. • WAN deployments increase the messaging demands on a SQLFire system. To avoid hangs related to WAN messaging, always set conserve-sockets to false for SQLFire members that participate in a WAN deployment. • Tables that are WAN-enabled must be present in each distributed system that you want to connect. • You can configure both partitioned tables and replicated tables to use a gateway sender. However, you must create replicated tables in the same server groups as the gateway sender(s) that you specify in the CREATE TABLE statement. • You must start the entire WAN system before you populate tables with data. This is required so that the WAN sites can remain in sync from the very beginning. Failing to do this causes exceptions during data update operations. See also Limitations of Multi-Site Replication on page 240. Steps to Configure a Multi-site Deployment To replicate a table's DML operations to one or more SQLFire clusters over a WAN, you configure the required WAN features in each SQLFire cluster. SQLFire provides SQL commands and extensions for creating and managing the gateway senders, gateways receivers, and tables that are used for WAN replication. Follow these steps to configure a multi-site deployment. Step Description Topic 1 Plan the topology of the connections among Multi-site Deployment on page 223 the multiple clusters. Configuring Multi-site (WAN) Deployments on page 237 2 Start the locators for each cluster, specifying Configure Locators for WAN Member the local cluster's distributed system ID and Discovery on page 242 the locator addresses associated with remote clusters. 3 Start data stores in each cluster, specifying the required server group memberships. 4 Optionally configure any disk stores that you Create and Start Gateway Sender on page 243 will use to persist DML operations that are queued before sending to a remote cluster. 5 Configure a gateway sender in each SQLFire Create and Start Gateway Sender on page 243 cluster that will send its data to another remote cluster for replication. Starting and Configuring SQLFire Servers on page 233 241 Deploying vFabric SQLFire Step Description Topic 6 Create tables in the source SQLFire cluster, Create Tables with Gateway Senders on page specifying one or more named gateway 244 senders that will send table DML operations for replication. 7 Create tables in the target SQLFire cluster Create Tables with Gateway Senders on page with identical column definitions (using the 244 same DDL commands). The cluster that will replicate DML operations must have identical tables available before it can apply the DML. 8 Configure a gateway receiver in each Create a Gateway Receiver on page 245 SQLFire cluster that will receive and replicate table DML operations from another remote system. 9 Test WAN replication by inserting rows in tables that have gateway senders, and verifying that those operations are replicated. 10 Start, stop, and manage gateway senders and Start and Stop Gateway Senders on page 245 receivers as necessary. 11 Change or remove gateway sender and Add and Remove Gateway Senders and gateway receiver configurations as necessary. Receivers on page 246 Configure Locators for WAN Member Discovery When you start a SQLFire locator in a WAN deployment, you must specify additional configuration options to identify each SQLFire cluster in the WAN. Important Configuration Notes • The -distributed-system-id option specifies a unique integer to identify the local cluster in which the locator participates. Configure all locators for a given WAN site using the same -distributed-system-id. • The -remote-locators option specifies the host and port numbers of one or more locators that identify remote SQLFire clusters. The local cluster use the remote locators to connect to the remote SQLFire systems for WAN replication. If a SQLFire cluster will replicate to multiple clusters (or if a remote customer uses more than one locator), specify multiple remote locator addresses in a comma-separated list when starting a locator as shown in these examples. • The -conserve-sockets option determines whether the locator will share a minimum number socket connections between applications that connect to the local system and local SQLFire members that distribute DML operations to remote WAN sites. Note: Because of the increased messaging requirements involved in WAN replication, always set conserve-sockets=false for SQLFire members that participate in a WAN deployment. 242 vFabric SQLFire User's Guide Configuring Multi-site (WAN) Deployments Procedure 1. Start a locator for a SQLFire cluster. For example, to start a locator for SQLFire cluster 1 shown in Figure 5: WAN configuration with multiple gateway senders on page 238: sqlf locator start -peer-discovery-address=ds1host -peer-discovery-port=10101 -locators=ds1host:10101 -conserve-sockets=false -distributed-system-id=1 -remote-locators=ds2host[20202],ds3host[30303] The above command configures the local SQLFire distributed system (with -distributed-system-id=1) to replicate to two different remote SQLFire distributed systems using standalone locators. Note: -peer-discovery-address and -peer-discovery-port identify the network connection that local SQLFire members use to discovery each other in the distributed system. -locators identifies all of the locators used in the distributed system (the above example uses the single, standalone locator that the sqlf command starts). These parameters are always used when starting locators, regardless of whether WAN replication is configured. See Using Locators on page 229 for more information. 2. To start a locator in SQLFire cluster 2, you would enter a command similar to: sqlf locator start -peer-discovery-address=ds2host -peer-discovery-port=20202 -locators=ds2host:20202 -conserve-sockets=false -distributed-system-id=2 -remote-locators=ds1host[10101],ds2host[20203] The preceding commands ensure that both cluster 1 and cluster 2 are associated with one another (and to cluster 3), and can replicate or receive data as necessary. Create and Start Gateway Sender A gateway sender represents a replication link to a single remote system. You can create multiple gateway senders in a SQLFire cluster to replicate data to multiple sites and/or to provide high availability for replicating data over a WAN. Prerequisites • Define the server groups on which you will deploy gateway senders. Using Server Groups to Manage Data on page 63 provides more information. Using server groups for gateway senders enables you to control which hosts can run gateway sender processes. Also, keep in mind that any replicated tables that use the gateway sender must be created in the same server groups as the gateway sender. • Optionally configure a disk store if you want to persist DML operations that are queued before replicating to a remote WAN site. Persisting the WAN queue ensures that DML operations can be queued for later replication if the connection between remote distributed systems is lost or temporarily blocked. Using Disk Stores to Persist Data on page 85 provides more information. Procedure After you create the necessary server groups and disk stores, use the CREATE GATEWAYSENDER statement to configure a new sender. You can configure the sender to start automatically or to start manually at a later time. 243 Deploying vFabric SQLFire • To create and automatically start a gateway sender in SQLFire cluster 1 to forward data to cluster 2 (as shown in Figure 5: WAN configuration with multiple gateway senders on page 238): CREATE GATEWAYSENDER cluster2sender ( REMOTEDSID 2 ENABLEPERSISTENCE true DISKSTORENAME cluster1store ) SERVER GROUPS (sender_group); The preceding statement starts gateway senders in the designated server group. The first gateway sender that starts becomes the primary sender for the local cluster. SQLFire will use the sender to replicate DML operations to a SQLFire cluster with distributed system ID 2. If there are additional SQLFire servers in the designated server group in cluster 1, SQLFire starts additional gateway senders on those members to act as secondary senders for high availability. • To start gateway senders manually at a later time, specify the MANUALSTART clause: CREATE GATEWAYSENDER 'cluster-1-sender' { REMOTEDSID 2 MANUALSTART TRUE ENABLEPERSISTENCE true DISKSTORENAME cluster-1-wan-store } SERVER GROUPS (secondary_sender_group) You can manually start the gateway sender using the instructions in Start and Stop Gateway Senders on page 245. The CREATE GATEWAYSENDER reference page contains additional information about options that you can configure when creating gateway senders. Create Tables with Gateway Senders To replicate table DML operations to a remote WAN site, you specify one or more named gateway senders when you create the table, or after you create a table (using the ALTER TABLE statement). The gateway senders that you specify then replicate the DML operations to the remote SQLFire clusters for which they are configured. Note: A table must have identical column definitions in each cluster in order for SQLFire to replicate it between clusters. Use the same DDL command in each cluster to create the table. If you achieve identical column definitions using different DDL commands (for example, by using ALTER TABLE to change one table to match another), then you may need to use SYS.INCREMENT_TABLE_VERSION to ensure that both tables have the same version in each cluster. Procedure 1. Use the GATEWAYSENDER clause with the CREATE TABLE statement to specify one or more gateway senders. For example, to create a WAN-replicated table in cluster 1 shown in Figure 5: WAN configuration with multiple gateway senders on page 238: CREATE TABLE test_table (ID INT NOT NULL, NAME VARCHAR(10)) GATEWAYSENDER(cluster-2-sender, cluster-3-sender) SERVER GROUPS (primary_sender_group, secondary_sender_group) Note: You can configure both partitioned tables and replicated tables to use a gateway sender. However, you must create replicated tables in the same server groups as the gateway sender(s) that you specify in the CREATE TABLE statement. 244 vFabric SQLFire User's Guide Configuring Multi-site (WAN) Deployments Create and Start Gateway Sender provides more information about configuring gateway senders. 2. Alternatively, use the SQLFire ALTER TABLE statement after you have created a table to add or remove gateway sender configurations. For example, if you did not supply a GATEWAYSENDER clause in the CREATE TABLE statement, you could add it later: ALTER TABLE test_table SET GATEWAYSENDER (cluster-2-sender, cluster-3-sender); 3. Repeat these steps to create the same table definitions in each SQLFire cluster that will replicate DML operations for those tables. The WAN replication process does not automatically create a table in the target SQLFire cluster. Create a Gateway Receiver To accept DML replication requests from remote SQLFire clusters, a SQLFire cluster requires a gateway receiver, which specifies the members that can receive connections from one or more remote gateway senders. A SQLFire cluster needs only a single gateway receiver, regardless of how many remote sites replicate data to the cluster. However, you can deploy multiple instances of a gateway receiver to different SQLFire members for high availability. Procedure Note: The SQLFire cluster that replicates DML operations from another cluster must have the same table definitions available to apply the DML operations. The tables that are used in WAN replication do not have to reside on the same SQLFire members that host the gateway receiver. 1. Use the CREATE GATEWAYRECEIVER statement and specify the server group to which you want to deploy the receiver. Also specify a range of port numbers to use for the receivers. SQLFire selects an unused port number from the range you specify when starting the receiver. If no port number in the range is available, an exception is thrown. For example: CREATE GATEWAYRECEIVER test_receiver (startport 1530 endport 1541) server groups (receivergroup1); This creates a receiver on receivergroup1 using an available port number from 1530 to 1540. 2. Query the GATEWAYRECEIVERS to determine which port number was selected to listen for WAN connections: select id, running_port, server_groups from sys.gatewayreceivers; ID |RUNNING_PORT |SERVER_GROUPS ----------------------------------------------------------TEST_RECEIVER |1537 |RECEIVERGROUP1 1 row selected In this example, the gateway receiver listens on port 1537. CREATE GATEWAYRECEIVER on page 497 provides additional information about creating receivers. Start and Stop Gateway Senders vFabric SQLFire can start a gateway sender process by default, but you can also specify a manual start when you create a sender. SQLFire automatically starts a gateway sender process when you use the CREATE GATEWAYSENDER statement. If you specify the MANUALSTART TRUE clause when creating a sender, you must manually start 245 Deploying vFabric SQLFire the sender processes using the SYS.START_GATEWAYSENDER procedure. Specify the name of the sender that you want to start, as in: CALL SYS.START_GATEWAYSENDER ("CLUSTER-1-SENDER"); This starts a primary gateway sender process in the configured server group, with secondary senders in standby mode. To stop all gateway sender processes, first use the SYS.WAIT_FOR_SENDER_QUEUE_FLUSH procedure to flush the gateway sender queue of events. Then use SYS.STOP_GATEWAYSENDER to stop the queue: CALL SYS.WAIT_FOR_SENDER_QUEUE_FLUSH('CLUSTER-1-SENDER', 'FALSE', 0); CALL SYS.STOP_GATEWAYSENDER ("CLUSTER-1-SENDER"); Add and Remove Gateway Senders and Receivers Use the ALTER TABLE command to modify the gateway senders configured for a table. Use DROP commands to completely remove gateway sender and gateway receiver configurations. Add Gateway Senders and Receivers The ALTER TABLE command enables you to add or remove gateway sender configurations on an existing table. The list of gateway senders that you include in the ALTER TABLE command replaces any existing sender configuration for the table. For example, consider the statement: ALTER TABLE test_table SET GATEWAYSENDER (cluster-2-sender, cluster-3-sender); If the table "test_table" had no previous gateway sender configurations associated with it, then the ALTER TABLE command associates two new senders with the table. If "test_table" was originally configured with a different gateway sender configuration, that configuration is removed and replaced with the new configuration (senders "cluster-2-sender" and "cluster-3-sender"). Remove Gateway Senders and Receivers To completely remove a gateway sender configuration from SQLFire, use the DROP GATEWAYSENDER statement and specify the sender name: DROP GATEWAYSENDER cluster-3-sender; To completely remove a gateway receiver configuration from SQLFire, use the DROP GATEWAYRECEIVER statement and specify the receiver name: DROP GATEWAYRECEIVER test_receiver; To remove all gateway senders from a table, stopping WAN replication for the table, use ALTER TABLE and specify no senders as in: ALTER TABLE test_table SET GATEWAYSENDER (); In all cases, the ALTER TABLE command only adds or removes gateway sender configurations for a particular table. The gateway sender configuration itself still remains in SQLFire, and may be used with other tables. Display Running Gateway Senders The SYS.GATEWAYSENDERS system table displays the configuration properties of all gateway senders you have configured in the SQLFire distributed system. You can execute queries against SYS.GATEWAYSENDERS and other system tables to display running gateway sender instances. The following query shows information about all members that are currently running a gateway sender instance: sqlf> select m.id, m.netservers, g.sender_id, g.server_groups from sys.members m, sys.gatewaysenders g > where groupsintersect(m.servergroups, g.server_groups); ID |NETSERVERS |SENDER_ID|SERVER_GROUPS 246 vFabric SQLFire User's Guide Configuring Multi-site (WAN) Deployments ---------------------------------------------------------------------------------192.168.125.142(13602):19974|localhost/127.0.0.1[1529]|C2SENDER |WANGROUP 192.168.125.142(13959):48326|localhost/127.0.0.1[1528]|C2SENDER |WANGROUP 2 rows selected 247 Chapter 42 Configuring Authentication and Authorization You secure a SQLFire deployment by configuring user authentication and SQL authorization, and enabling encryption between members using SSL/TLS. Note: Many topics in this chapter were adapted from the Apache Derby documentation source files, and are subject to the Apache license: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Configuring User Authentication When you enable user authentication, a valid username and password are required in order to start up a new SQLFire member in the distributed system; join an existing distributed system; and connect to a running SQLFire distributed system. SQLFire verifies the name and password against a repository of users that is defined for the system. Authentication is not enabled by default. SQLFire authenticates users credentials against a repository of users that you specify. SQLFire provides a built-in repository, or you can configure SQLFire to use an LDAP directory service or a custom authentication service that you create. Note: The SQLFire built-in authentication mechanism is suitable only for development and testing purposes. Production systems should use an LDAP repository or custom directory service, and should secure network connections using SSL/TLS. 249 Deploying vFabric SQLFire After SQLFire authenticates a user, it grants the user access to the SQLFire distributed system, either by starting up the SQLFire member in a new distributed system, joining the member to an existing distributed system, or simply connecting to a distributed system as a client. Authenticated users may also access to database objects according to the SQL authorization configuration. (SQL authorization is not enabled by default). Note: Because SQLFire can be embedded within a Java application, it is also possible to deploy a system in which the Java application, rather than the embedded SQLFire process, handles user authentication. User Authentication and Member Ownership The authenticated system user that starts up a SQLFire member is the owner of that member JVM. The owner of a SQLFire member cannot be changed after the JVM is started. However, member ownership can be changed by stopping the member process and then restarting it using the credentials of another user. The owner of a SQLFire member owns any schemas and database objects that they create in the distributed system. The owner also owns any schemas and database objects in the JVM that were created by other JVM owners. In other words, SQLFire treats all JVM owners interchangeably when a SQLFire member is booted. See also SQLFire Member JVM Owner on page 258. Enable User Authentication To enable user authentication with SQLFire, you must use a SQLFire locator for member discovery. SQLFire uses mutual authentication between the SQLFire locator and subsequent SQLFire members that boot and join the distributed system. User authentication is not supported if you use multicast for member discovery. Procedure 1. For each member of the SQLFire cluster (servers, locators, and accessors), set the sqlfire.auth-provider property to enable user authentication and to specify the mechanism that SQLFire uses to authenticate users. For servers and locators, specify -auth-provider=provider_name at the command line, or define the sqlfire.auth-provider=provider_name property in the sqlfire.properties file. For development and testing only, specify BUILTIN as the provider name to use the SQLFire built-in authentication mechanism. For production purposes, specify LDAP to use an existing LDAP repository, or specify the name of a custom provider class that implements the UserAuthenticator interface. 2. Configure user credentials in your specified authentication provider. See Creating Users for BUILTIN Authentication on page 251 or Configuring LDAP Directory Service on page 253. Note: If you start a SQLFire system with user authentication enabled but without defining at least one user, you will not be able to shut down the system at once with sqlf shut-down-all. To create users, see Creating Users for BUILTIN Authentication on page 251 or Configuring LDAP Directory Service on page 253. 3. Start one or more SQLFire locators with the authorization configuration, before starting any additional SQLFire data stores or accessors. When using BUILTIN authentication, the locator must define all system user accounts as well as the authentication provider for the distributed system as a whole. SQLFire uses the specified provider and users to perform mutual authentication when new members attempt to join the distributed system. 4. When shutting down the distributed system, use sqlf shut-down-all with authenticated user credentials. By default this command shuts down all servers and accessors, but leaves standalone locator members running. Always leave at least one locator running in the distributed system, until all data stores have finished shutting down. 250 vFabric SQLFire User's Guide Configuring Authentication and Authorization Example The following sqlfire.properties entries show a SQLFire member that is configured to use SQLFire built-in authentication: sqlfire.auth-provider=BUILTIN mcast-port=0 The mcast-port=0 entry indicates that multicast is not used in the SQLFire distributed system. Valid locator properties would need to be supplied when starting the SQLFire server, as well as the credentials for a SQLFire user as described in Creating Users for BUILTIN Authentication on page 251. Creating Users for BUILTIN Authentication The SQLFire BUILTIN authentication provider is suitable for development and testing only. When using this security mechanism, the SQLFire system maintains the repository of username and password information. BUILTIN User Accounts The BUILTIN provider supports two different types of user account: • System user accounts are visible to all members of the SQLFire system, and have privileges to join members to the cluster and shut down cluster members. The list of valid system users is established using system properties when you boot a SQLFire server or locator. You should use only a few system-level users in a SQLFire deployment (for example, one system user for a standalone locator and one for SQLFire servers). You create user names and passwords for system users by specifying them with the sqlfire.user.= property in the sqlfire.properties file. See Create and View System Users on page 251. • Distributed system user accounts are used to establish connections to a SQLFire cluster and to protect database resources using SQL authorization. You define distributed system user credentials by connecting to a running SQLFire system and executing a built-in procedure. Privileges on individual database resources are then granted using SQL commands. See Create Distributed System Users on page 253. Note: The SQLFire built-in authentication mechanism is suitable only for development and testing purposes. Production systems should use LDAP or a user-defined class for authentication. Production systems should also use SSL/TLS to protect network connections. Create and View System Users System users are established at boot time, and have privileges to join and start SQLFire servers and locators. Procedure 1. Create a system user for SQLFire by specifying user name=password at boot time using the sqlfire.user.UserName system property. SQLFire user names are SQL92 identifiers, and are case-sensitive for user authentication. Delimited identifiers are allowed. For example, the following property defines a username of "FRed" with the password "java": sqlfire.user."FRed"=java Note: You can use either a plain-text password or an encrypted password as the value of sqlfire.user.UserName. See Encrypt the Password of a System User on page 252. 2. Include the property definitions for system users in the sqlfire.properties file for each SQLFire server and standalone locator. 251 Deploying vFabric SQLFire For example, this listing shows a sqlfire.properties file the defines a "locatoradmin" and "serveradmin" system user: sqlfire.auth-provider=BUILTIN mcast-port=0 sqlfire.user.locatoradmin=locatorpassword sqlfire.user.serveradmin=serverpassword 3. To boot a standalone locator using the above properties file, specify a configured system user with the -user option as in: sqlf locator start -user=locatoradmin -password If you leave the -password option empty, SQLFire prompts you for the password. Note: Built-in system users are defined when you boot the SQLFire locator. Other SQLFire members that join the system must specify one of the same system users that are defined in the locator. If you need to change the password of a system user, you must stop all members of the distributed system, and then restart them (beginning with the locator), specifying the new username definition when you start. 4. Use the SYS.SHOW_USERS procedure to view the configured BUILTIN users in a SQLFire distributed system. Note: Keep in mind that sqlfire.user.UserName defines a user credential, and -user specifies an available credential to use for booting the server or locator. Both properties are required. For example, if you specified all properties at the command line rather than in sqlfire.properties, the command to boot the locator is: sqlf locator start -auth-provider=BUILTIN -sqlfire.user.locatoradmin=locatorpassword -user=locatoradmin -password=locatorpassword Encrypt the Password of a System User To avoid storing system user passwords in plain text in the sqlfire.properties file, use the sqlf encrypt-password command to generate encrypted placeholder text for the password. For example: sqlf encrypt-password Enter User Name: locatoradmin Enter Password: locatorpassword Re-enter Password: locatorpassword Encrypted to v23b60584174091d1d7b3bad3728a55500915424516037 Store the encrypted value in the sqlfire.properties file in place of the clear text password for the specified user name: sqlfire.user.locatoradmin=v23b60584174091d1d7b3bad3728a55500915424516037 Change a System User Password Built-in system users are defined when you boot the SQLFire locator. Other SQLFire members that join the system must specify one of the same system users that are defined in the locator. If you need to change the password of a system user, you must stop all members of the distributed system, and then restart them (starting with the locator), specifying the new username definition when you start. To change the password of an existing system user, either specify a new password when your start a SQLFire member using the sqlfire.user.UserName system property, or generate a new encrypted password using sqlf encrypt-password and place the new encrypted password in the sqlfire.properties file. See Create and View System Users on page 251 or Encrypt the Password of a System User on page 252 for details. 252 vFabric SQLFire User's Guide Configuring Authentication and Authorization Note: Regardless of which method you use to define the new password, you must restart all SQLFire members (including locators) using the new password. You cannot change a system password user on only a subset of the SQLFire members. This limitation applies only to system users defined in the BUILTIN authentication schema. LDAP authentication occurs outside of the SQLFire system, so passwords can be changed without affecting available SQLFire members. Create Distributed System Users Create user accounts to protect database resources. To define distributed system users, you must first connect to a SQLFire system and then execute a system procedure to create a user account. Note: To create the first user account, log in using an established SQLFire system user. After creating a distributed system user, you can connect and assign database privileges using the new account. For example: sqlf connect peer 'locators=localhost:10334;mcast-port=0;user=SB;auth-provider=BUILTIN;sqlfire.user.SB=PSB;password=PSB'; call sys.create_user('sqlfire.user.newuser', 'newpassword'); disconnect; After creating one or more distributed system user accounts, you can use those credentials, instead of a system user credential, to connect to SQLFire: sqlf connect client 'localhost:10334;user=newuser;password=newpassword'; Use distributed system user accounts with the GRANT and REVOKE statements to manage access to database resources. See Configuring User Authorization on page 258. Configuring LDAP Directory Service SQLFire can authenticate users against an existing LDAP directory service within your enterprise. LDAP (lightweight directory access protocol) provides an open directory access protocol running over TCP/IP. An LDAP directory service can quickly authenticate a user's name and password. The runtime library provided with the Java Development Kit (JDK) includes libraries that allow you to access an LDAP directory service. See the API documentation for the javax.naming.ldap package at http://download.oracle.com/javase/6/docs/api/; the LDAP section of the JNDI tutorial at http://download.oracle.com/javase/tutorial/jndi/ldap/; and the LDAP section of the JNDI specification at http://download.oracle.com/javase/1.5.0/docs/guide/jndi/spec/jndi/jndi.5.html#pgfId=999241. Examples of LDAP service providers include the 389 Directory Server and OpenLDAP. Configure SQLFire to Use Your LDAP Directory Service When configuring vFabric SQLFire to use LDAP as your authentication service, you must specify which LDAP server to use. Procedure 1. Set the auth-provider property to "LDAP" when you start each locator and server in the SQLFire distributed system. 2. When you set the auth-provider property to "LDAP," SQLFire uses LDAP for authenticating distributed system members as well as clients to the distributed system. For this reason, SQLFire members must supply the user option (and optionally, the password option) at startup. If you omit the password option, the SQLFire member prompts you for a password at the command line. 253 Deploying vFabric SQLFire 3. Set the sqlfire.auth-ldap-server property to the URL to the LDAP server. For example: sqlfire.auth-ldap-server=ldap://server:port/ You can specify the LDAP server with only the server name, the server name, and its port number separated by a colon, or an "ldap" URL. If a full URL is not provided, SQLFire uses unencrypted LDAP by default. To use SSL-encrypted LDAP, provide a URL starting with "ldaps://". Note: This property must be specified either as a Java system property or in the sqlfire.properties file. For example, when booting a new SQLFire server with sqlf, you could use the command-line option -J-Dsqlfire.auth-ldap-server=ldaps://server:port/ to specify the Java system property. 4. If you use SSL-encrypted LDAP and your LDAP server certificate is not recognized by a valid Certificate Authority (CA), create a local trust store for each SQLFire member and import the LDAP server certificate to the trust store. See http://docs.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#CreateKeystore for more information. 5. If you performed step 3, include the javax.net.ssl.trustStore and javax.net.ssl.trustStorePassword system properties when you start individual SQLFire members. For example: sqlf server start -dir=./server -locators=localhost[10101] -client-port=1528 -auth-provider=LDAP \ -J-Dsqlfire.auth-ldap-server=ldaps://ldapserver:636/ -user=user_name -password=user_pwd \ -J-Dsqlfire.auth-ldap-search-dn=uid=sqlfire1,ou=ldapExample,dc=gemstone,dc=com \ -J-Dsqlfire.auth-ldap-search-pw=sqlfire1 \ -J-Dsqlfire.auth-ldap-search-base=ou=ldapTesting,dc=gemstone,dc=com \ -J-Djavax.net.ssl.trustStore=/Users/yozie/vFabric_SQLFire_11_bNNNNN/keystore_name \ -J-Djavax.net.ssl.trustStorePassword=keystore_password Note: javax.net.ssl.trustStore and javax.net.ssl.trustStorePassword must be specified as Java system properties (using the -J option on the sqlf command line). Note: LDAP server and search properties must be set to the same value for each member of the SQLFire distributed system. However, individual SQLFire members can be started using different authenticated user credentials, trust stores, and so forth. Guest Access to Search for DNs In an LDAP system, users are hierarchically organized in the directory as a set of entries. An entry is a set of name-attribute pairs identified by a unique name, called a DN (distinguished name). An entry is unambiguously identified by a DN, which is the concatenation of selected attributes from each entry in the tree along a path leading from the root down to the named entry, ordered from right to left. For example, a DN for a user might look like this: cn=mary,ou=People,dc=example,dc=com uid=mary,ou=People,dc=example,dc=com 254 vFabric SQLFire User's Guide Configuring Authentication and Authorization The allowable entries for the name are defined by the entry's objectClass. An LDAP client can bind to the directory (successfully log in) if it provides a user ID and password. The user ID must be a DN, the fully qualified list of names and attributes. This means that the user must provide a very long name. Typically, the user knows only a simple user name (for example, the first part of the DN above, mary). With SQLFire, you do not need the full DN, because an LDAP client (SQLFire) can go to the directory first as a guest or even an anonymous user, search for the full DN, then rebind to the directory using the full DN (and thus authenticate the user). SQLFire typically initiates a search for a full DN before binding to the directory using the full DN for user authentication. SQLFire does not initiate a search in the following cases: • You have set sqlfire.auth-ldap-search-filter to sqlfire.user. • A user DN has been cached locally for the specific user with the sqlfire.user.UserName property. For more information, see sqlfire.auth-ldap-search-filter. Some systems permit anonymous searches; other require a user DN and password. You can specify a user's DN and password for the search with the properties listed below. In addition, you can limit the scope of the search by specifying a filter (definition of the object class for the user) and a base (directory from which to begin the search) with the properties listed below. Note: Each of the following properties must be specified as a system property when you boot a SQLFire peer. For example, when booting a new SQLFire server with sqlf, use the command-line option -J-Dsqlfire.auth-ldap-search-base=searchbase. • sqlfire.auth-ldap-search-dn (required if your LDAP provider does not support anonymous binding) Specifies the DN with which to bind (authenticate) to the server when searching for user DNs. This parameter is optional if anonymous access is supported by your server. If specified, this value must be a DN recognized by the directory service, and it must also have the authority to search for the entries. If not set, it defaults to an anonymous search using the root DN specified by the sqlfire.auth-ldap-search-base property. For example: uid=guest,dc=example,dc=com • sqlfire.auth-ldap-search-pw (optional) Specifies the password to use for the guest user configured above to bind to the directory service when looking up the DN. If not set, it defaults to an anonymous search using the root DN specified by the sqlfire.auth-ldap-search-base property. myPassword • sqlfire.auth-ldap-search-base (required) Specifies the root DN of the point in your hierarchy from which to begin a guest search for the user's DN. For example: ou=people,dc=example,dc=com By default, SQLFire tries to bind the anonymous user for searching when you configure sqlfire.auth-ldap-search-base. If your LDAP server does not support anonymous binding, also configure sqlfire.auth-ldap-search-dn and sqlfire.auth-ldap-search-pw. When using Netscape Directory Server, set this property to the root DN, the special entry to which access control does not apply (optional). To narrow the search, you can specify a user's objectClass. 255 Deploying vFabric SQLFire • sqlfire.auth-ldap-search-filter (optional) Set sqlfire.auth-ldap-search-filter to a logical expression that specifies what constitutes a user for your LDAP directory service. The default value of this property is objectClass=inetOrgPerson. For example: objectClass=person If you include the token %USERNAME% in the sqlfire.auth-ldap-search-filter definition, then SQLFire replaces the token with the user name that is being authenticated. If do not provide a search-filter, then SQLFire uses the default search filter: (&(objectClass=inetOrgPerson)(uid=%USERNAME%)) If you provide a search filter that does not have the %USERNAME% token, then SQLFire prepends the token to the default search filter. For example: (&()(objectClass=inetOrgPerson)(uid=%USERNAME%)) Example LDAP Search Configuration For example, consider the following LDAP search invoked using the OpenLDAP ldapsearch tool: ldapsearch -b ou=users,dc=domain,dc=com /* base DN */ -x /* non-SASL plain-text authentication */ -D uid=test,ou=ldapTesting,dc=domain,dc=com /* bind DN */ -w test /* bind password */ "(&(objectClass=user)(uid=user1))" /* filter */ To configure this search with SQLFire you would use the properties: sqlfire.auth-ldap-search-base=ou=users,dc=domain,dc=com sqlfire.auth-ldap-search-filter=(&(objectClass=user)(uid=%USERNAME%)) sqlfire.auth-ldap-search-dn=uid=test,ou=ldapTesting,dc=domain,dc=com sqlfire.auth-ldap-search-pw=test LDAP Restrictions and Performance Guidelines SQLFire does not support LDAP groups. For performance reasons, the LDAP directory server should be in the same LAN as SQLFire. SQLFire does not cache the user's credential information locally and thus must connect to the directory server every time a user connects. Connection requests that provide the full DN are faster than those that must search for the full DN. JNDI-Specific Properties for External Directory Services SQLFire allows you to set a few advanced JNDI properties, which you can set by any supported means of setting SQLFire properties. Typically you would set these at the same level (database or system) for which you configured the external authentication service. The list of supported properties can be found in Appendix A: JNDI Standard Environment Properties in the Java Naming and Directory API at http://download.oracle.com/javase/1.5.0/docs/guide/jndi/spec/jndi/properties.html. The external directory service must support the property. Each JNDI provider has its set of properties that you can set within the SQLFire system. For example, you can set the property java.naming.security.authentication to allow user credentials to be encrypted on the network if the provider supports it. You can also specify that SSL be used with LDAP (LDAPS). 256 vFabric SQLFire User's Guide Configuring Authentication and Authorization JMX and Authentication If you use the SQLFire JMX Agent to administer and manage an authentication-enabled distributed system, the agent must provide security credentials. Security properties cannot be passed to a JMX Agent on the command line, but they can be supplied at startup by adding the security-specific Java system properties (-D properties). With the properties specified, the call to Agent.connectToSystem causes the agent to be authenticated with the distributed system. SQLFire security does not manage RMI clients to the JMX Agent. Once connected, the JMX Agent is considered authenticated and any RMI client has access to the connected distributed system. For RMI client authentication, use MX4J security. See Using Java Management Extensions (JMX) on page 303 for more information. User Names in Authentication and Authorization When working with both user authentication and user authorization, you need to understand how user names are treated by each system. User Names and Authorization Identifiers User names within the SQLFire system are known as authorization identifiers. The authorization identifier is a string that represents the name of the user, if one was provided in the connection request. For example, the built-in function CURRENT_USER returns the authorization identifier for the current user. Once the authorization identifier is passed to the SQLFire system, it becomes an SQL92Identifier. A SQL92Identifier is a kind of identifier that represents a database object such as a table or column. These identifiers are case-insensitive (they are converted to all caps) unless delimited with double quotes, are limited to 128 characters, and have other limitations. User names must be valid authorization identifiers even if user authentication is turned off, and even if all users are allowed access to all databases. For more information about SQL92Identifiers, see Standard SQL Identifiers on page 485. Conversion of User Name to Authorization Identifier If an external authentication system is used, the conversion of the user's name to an authorization identifier does not happen until after authentication has occurred but before user authorization. Imagine, for example, a user named Fred. • Within the user authentication system, Fred is known as FRed. Your external user authorization service is case-sensitive, so Fred must always type his name that way. connect client 'localhost:1527;user=FRed;password=flintstone'; • Within the SQLFire user authorization system, Fred becomes a case-insensitive authorization identifier. Fred is known as FRED. • When specifying which users are authorized to access the system, you must list Fred's authorization identifier, FRED (which you can type as FRED, FREd, or fred, since the system automatically converts it to all-uppercase). sqlfire.authz-full-access-users=sa,FRED,mary Let's take a second example, where Fred has a slightly different name within the user authentication system. • Within the user authentication system, Fred is known as Fred!. You must now put double quotes around the name, because it is not a valid SQL92Identifier . (SQLFire knows to remove the double quotes when passing the name to the external authentication system.) connect client 'localhost:1527;user="Fred!";password=flintstone'; 257 Deploying vFabric SQLFire • Within the SQLFire user authorization system, Fred becomes a case-sensitive authorization identifier. Fred is known as Fred!. • When specifying which users are authorized to access the accounting database, you must list Fred's authorization identifier, "Fred!" (which you must always delimit with double quotation marks). sqlfire.authz-full-access-users=sa,"Fred!",manager As shown in the first example, your external authentication system may be case-sensitive, whereas the authorization identifier within SQLFire may not be. If your authentication system allows two distinct users whose names differ by case, delimit all user names within the connection request to make all user names case-sensitive within the SQLFire system. In addition, you must also delimit user names that do not conform to SQL92Identifier rules with double quotes. SQLFire Member JVM Owner The term JVM owner refers to the authorization identifier of the user who booted the SQLFire member JVM. If you enable or plan to enable SQL authorization, controlling the identity of the JVM owner becomes important. If a member is started without supplying a user (only possible if authentication is not enabled), the JVM owner is set to the default authorization identifier, "APP", which is also the name of the default schema. The JVM owner has automatic SQL level permissions when SQL authorization is enabled. See Configuring User Authorization on page 258 for more information. Attention: The JVM owner cannot be changed after the SQLFire member starts. Instead, you must stop the member and then restart it using different user credentials. If you plan to run with SQL authorization enabled, start new SQLFire members as the user that you want to be the JVM owner. Configuring User Authorization When you specify user authorizations, SQLFire verifies that a user has been granted permission to access a schema, database object, or a SQL action. • Connection Authorization and SQL Standard Authorization on page 258 • User Authorization Properties on page 258 • How User Authorization Properties Work Together on page 259 • Changing Connection Authorization Settings on page 259 Connection Authorization and SQL Standard Authorization There are two types of user authorization in SQLFire: connection authorization and SQL standard authorization. Connection authorization specifies the basic access that users have when they connect to the distributed system. SQL authorization controls the permissions that users have on database objects or for SQL actions. You set the user authorization properties in SQLFire as system-level properties, either at the command line or connection string when booting SQLFire members, or in the sqlfire.properties file. User Authorization Properties You can set properties to control user authorizations for SQLFire. Some properties set the default access mode for all users. Other properties set the default level of access for specific user IDs. The properties that affect authorization are: • sqlfire.authz-default-connection-mode —Sets the access mode for all users, overriding any fine-grained privileges that you may have granted using the GRANT statement. Configure this property only if you want to override the access mode for all users. 258 vFabric SQLFire User's Guide Configuring Authentication and Authorization • sqlfire.authz-full-access-users and sqlfire.authz-read-only-access-users —These properties specify one or more user IDs that have read-write access and read-only access to the distributed system as a whole. • sqlfire.sql-authorization —Enables SQL standard authorization. Use sqlfire.sql-authorization to control whether object owners can grant and revoke permission for other users to perform SQL actions on their database objects. The default setting for sqlfire.sql-authorization is FALSE. However, if you start a SQLFire member with sqlf and you include the -auth-provider option to specify a client authentication mechanism, then SQL authorization is enabled by default. When SQL authorization, object owners can use the GRANT and REVOKE SQL statements to set the user permissions for specific database objects or for specific SQL actions. If you do not configure user authorizations for a specific user ID, the user ID inherits whatever authorization is set as the default user authorization for the SQLFire member (sqlfire.authz-default-connection-mode). Tip: If you set the sqlfire.authz-default-connection-mode property to noAccess or readOnlyAccess, you should allow at least one user read-write access. Otherwise, depending on the default connection authorization that you specify, your system may contain database objects that cannot be accessed or changed. How User Authorization Properties Work Together The sqlfire.authz-default-connection-mode and sqlfire.sql-authorization properties work together. The default settings for these properties allow anyone to access and drop the database objects that they create. You can change the default access mode by specifying different settings for these properties. • When the sqlfire.sql-authorization property is FALSE, the ability to read from or write to database objects is determined by the setting for the sqlfire.authz-default-connection-mode property. If sqlfire.authz-default-connection-mode is set to readOnlyAccess, users can access all of the database objects but they cannot update or drop those objects. • When sqlfire.sql-authorization is TRUE, the ability to read from or write to database objects is initially restricted to the owner of those database objects. The owner must explicitly grant permission for others to access the database objects. No one but the owner of an object or the JVM owner can drop the object. • The access mode specified for the sqlfire.authz-default-connection-mode property overrides the permissions that are granted by the owner of a database object. For example, if a user is granted INSERT privileges on a table but the user only has read-only connection authorization, the user cannot insert data into the table. Changing Connection Authorization Settings Connection authorization properties are fixed for the duration of a connection. Establish a new connection in order to change authorization properties. Set the SQL Standard Authorization Mode Use the sqlfire.sql-authorization property to enable SQLFire standard authorization. The sqlfire.sql-authorization property controls the ability for object owners to grant and revoke permission for users to perform actions on database objects that they create. The valid settings for the sqlfire.sql-authorization property are: • TRUE • FALSE The default setting for the sqlfire.sql-authorization property is FALSE. 259 Deploying vFabric SQLFire After you set the sqlfire.sql-authorization property to TRUE, you cannot set the property back to FALSE. When you enable this property, all new database schemas have SQL authorization enabled. To enable SQL standard authorization for the entire system, set the sqlfire.sql-authorization property as a system property. For example, add this line to sqlfire.properties: sqlfire.sql-authorization=true Set the Default Connection Access Mode Use the sqlfire.authz-default-connection-mode property to specify the default type of access that users have when they connect to the distributed system. The valid settings for the sqlfire.authz-default-connection-mode property are: • noAccess • readOnlyAccess • fullAccess If you do not specify a setting for the sqlfire.authz-default-connection-mode property, the default access setting is fullAccess. To set the default connection access mode, specify the system property in sqlfire.properties or when booting the SQLFire member. Set the Authorizations for Individual Users Use the sqlfire.authz-full-access-users and sqlfire.authz-read-only-access-users properties to specify the user IDs that have read-write access and read-only access to a distributed system. You can specify multiple user IDs by using a comma-separated list, with no spaces between the comma and the next user ID. Specify one or both system properties in sqlfire.properties or when booting the SQLFire member. Read-only and Full Access Permissions The actions that users can perform on a database objects is determined by the type of access that users have. The following table lists the actions that users can perform based on the type of access that a user is granted. Table 5: Actions that are authorized by type of access Action Read-only access Full access Executing SELECT statements X X Executing INSERT, UPDATE, or DELETE statements X Executing DDL statements X Adding or replacing jar files X User Authorization Exceptions SQL exceptions are returned when errors occur with user authorizations. SQLFire validates the database properties when you set the properties. An exception is returned if you specify an invalid value when you set these properties. 260 vFabric SQLFire User's Guide Configuring Authentication and Authorization After you set the sqlfire.sql-authorization property to TRUE, you cannot set the property back to FALSE. If a user attempts to connect to a distributed system but is not authorized to connect, SQLException 04501 is returned. If a user with read-only access attempts to write to the system, SQLException 08004 - connection refused is returned. Set User Permissions for Database Objects in SQL Standard Authorization When the SQL standard authorization mode is enabled, object owners can use the GRANT and REVOKE SQL statements to set the user permissions for specific database objects or for specific SQL actions. The SQL standard authorization mode is a SQL2003 compatible access control system. You enable the SQL standard authorization mode by setting the sqlfire.sql-authorization property to TRUE. While SQLFire has a simpler database access mode which can be set to provide users with full, read-only, or no access authorization, this simpler access mode is less appropriate for most client-server database configurations. When users or applications issue SQL statements directly against the database, the SQL authorization mode provides a more precise mechanism to limit the actions that users can take on the database. • GRANT and REVOKE Privileges on page 261 • Set Public and Individual User Privileges on page 261 • Set Permissions on Views, Triggers, and Constraints on page 262 GRANT and REVOKE Privileges The GRANT statement is used to grant specific permissions to users. The REVOKE statement is used to revoke permissions. The grant and revoke privileges are: • DELETE • EXECUTE • INSERT • SELECT • REFERENCES • TRIGGER • UPDATE When a table, view, function, or procedure is created, the person that creates the object is referred to as the owner of the object. Only the object owner and the SQLFire Member JVM Owner on page 258 have full privileges on the object. No other users have privileges on the object until the object owner grants privileges to them. Set Public and Individual User Privileges The object owner can grant and revoke privileges for specific users or for all users. The keyword PUBLIC is used to specify all users. When PUBLIC is specified, the privileges affect all current and future users. The privileges granted and revoked to PUBLIC and to individual users are independent. For example, a SELECT privilege on table t is granted to both PUBLIC and to the user harry. The SELECT privilege is later revoked from user harry, but user harry has access to table t through the PUBLIC privilege. Exception: When you create a view, trigger, or constraint, SQLFire first checks to determine if you have the required privileges at the user-level. If you have the user-level privileges, the object is created and is dependent on that user-level privilege. If you do not have the required privileges at the user-level, SQLFire checks to determine if you have the required privileges at the PUBLIC level. If you have the PUBLIC level privileges, the object is created and is dependent on that PUBLIC level privilege. After the object is created, if the privilege on which the object depends on is revoked, the object is automatically dropped. 261 Deploying vFabric SQLFire SQLFire does not try to determine if you have other privileges that can replace the privileges that are being revoked. Example 1 User zhi creates table t1 and grants SELECT privileges to user harry on table t1. User zhi grants SELECT privileges to PUBLIC on table t1. User harry creates view v1 with the statement SELECT * from zhi.t1. The view depends on the user-level privilege that user harry has on t1. Subsequently, user zhi revokes SELECT privileges from user harry on table t1. As a result, the view harry.v1 is dropped. Example 2 User anita creates table t1 and grants SELECT privileges to PUBLIC. User harry creates view v1 with the statement SELECT * from anita.t1. The view depends on the PUBLIC level privilege that user harry has on t1 since user harry does not have user-level privileges on table t1 when he creates the view harry.v1. Subsequently, user anita grants SELECT privileges to user harry on table anita.t1. The view harry.v1 continues to depend on PUBLIC level privilege that user harry has on t1. When user anita revokes SELECT privileges from PUBLIC on table t1, the view harry.v1 is dropped. Set Permissions on Views, Triggers, and Constraints Views, triggers, and constraints operate with the permissions of the owner of the view, trigger, or constraint. For example, user anita wants to create a view using the following statement: CREATE VIEW s.v(vc1,vc2,vc3) AS SELECT t1.c1,t1.c2,f(t1.c3) FROM t1 JOIN t2 ON t1.c1 = t2.c1 WHERE t2.c2 = 5 User anita needs the following permissions to create the view: • Ownership of the schema s, so that she can create something in the schema • Ownership of the table t1, so that she can allow others to see columns in the table • SELECT permission on column t2.c1 and column t2.c2 • EXECUTE permission on function f When the view is created, only user anita has SELECT permission on it. User anita can grant SELECT permission on any or all of the columns of view s.v to anyone, even to users that do not have SELECT permission on t1 or t2, or EXECUTE permission on f. User anita grants SELECT permission on view s.v to user harry. When user harry issues a SELECT statement on the view s.v, SQLFire checks to determine if user harry has SELECT permission on views.v. SQLFire does not check to determine if user harry has SELECT permission on t1, or t2, or EXECUTE permission on f. Permissions on triggers and constraints work the same way as permissions on views. When a view, trigger, or constraint is created, SQLFire checks that the owner has the required permissions. Other users do not need to have those permissions to perform actions on a view, trigger, or constraint. If the required permissions are revoked from the owner of a view, trigger, or constraint, the object is dropped as part of the REVOKE statement. See also GRANT on page 536 and REVOKE on page 539. Configuring Network Encryption and Authentication with SSL/TLS By default, all SQLFire network traffic is unencrypted, with the exception of user names and user passwords, which can be encrypted separately. There is also no network layer access control mechanism. For deployment scenarios where these are possible security issues, the SQLFire Network Server supports network security with Secure Socket Layer/Transport Layer Security (SSL/TLS). 262 vFabric SQLFire User's Guide Configuring Authentication and Authorization With SSL/TLS, the client/server communication protocol is encrypted, and independently of each other, both client and server can require certificate-based authentication of each other. It is assumed that the reader is somewhat familiar with SSL, key pairs, and certificates. This documentation is also based on the Java Development Kit (JDK) and its keytool application. For the remainder of this section, the term SSL is used for SSL/TLS and the term peer is used for the other part of the communication (The server's peer is the client and vice versa). SSL for SQLFire (both for client and for server) operates in three possible modes: off The default, no SSL encryption basic SSL encryption, no peer authentication peerAuthentication SSL encryption and peer authentication You can set peer authentication on the server or on the client or on both. Peer authentication means that the other side of the SSL connection is authenticated based on a trusted certificate installed locally. Alternatively, you can install a Certification Authority (CA) certificate locally and the peer has a certificate signed by that authority. How to achieve this is not described in this document. Consult your Java environment documentation for details. Attention: If a plaintext client tries to communicate with an SSL server or an SSL client tries to communicate with a plaintext server, the plaintext side of the communication will see the SSL communication as noise and report protocol errors. Generate Key Pairs and Certificates For SSL operation, the server always needs a key pair. In general, fpr one end of the communication to authenticate its partner, the first end needs to install a certificate generated by the partner. If the server runs in peer authentication mode (the server authenticates the clients), then each client needs its own key pair. The key pair is located in a file which is called a key store and the JDK's SSL provider needs the system properties javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword to access the key store. The certificates of trusted parties are installed in a file called a trust store. The JDK's SSL provider needs the system properties javax.net.ssl.trustStore and javax.net.ssl.trustStorePassword to access the trust store. Generate Key Pairs Key pairs are generated with keytool -genkey. The simplest way to generate a key pair is to do the following: keytool -genkey -keystore keytool prompts for needed information like identity details and passwords. For example, to generate the server key pair: keytool -genkey -alias mySQLFireServer -keystore serverKeyStore.key Generate a client key pair: keytool -genkey -alias aSQLFireClient -keystore clientKeyStore.key Consult the JDK documentation for more information on keytool. 263 Deploying vFabric SQLFire Generate Certificates Generate certificates with keytool -export as follows: keytool -export -alias -keystore \ -rfc -file For example, to generate a server certificate: keytool -export -alias mySQLFireServer -keystore serverKeyStore.key \ -rfc -file myServer.cert Generate a client certficate: keytool -export -alias aSQLFireClient -keystore clientKeyStore.key \ -rfc -file aClient.cert The certificate file may then be distributed to the relevant parties. Install Certificate in a Trust Store Install a certificate in a trust store with keytool -import as follows: keytool -import -alias -file \ -keystore Install a client certificate in the server's trust store: keytool -import -alias aSQLFireClient -file aClient.cert -keystore serverTrustStore.key Install the server certificate in a client's trust store: keytool -import -alias mySQLFireServer -file myServer.cert -keystore clientTrustStore.key Start the Server with SSL/TLS You activate SSL at the server side with the property derby.drda.sslMode (default off) or the -ssl option for the server start command. For server SSL/TLS, a server key pair needs to be generated. If the server is going to do client authentication, the client certificates need to be installed in the trust store.These operations are described in Generate Key Pairs and Certificates on page 263. • Starting the Server with Basic SSL Encryption on page 264 • Starting a Server That Authenticates Clients on page 265 Starting the Server with Basic SSL Encryption When the SSL mode is set to basic, the server only accepts SSL encrypted connections. The properties javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword need to be set with the proper values. Example sqlf server start -J-Djavax.net.ssl.keyStore=serverKeyStore.key \ -J-Djavax.net.ssl.keyStorePassword=qwerty \ -sqlfire.drda.sslMode=basic 264 vFabric SQLFire User's Guide Configuring Authentication and Authorization Starting a Server That Authenticates Clients When the server's SSL mode is set to peerAuthentication, the server authenticates its clients' identity in addition to encrypting network traffic. In this situation, the server's trust store must contain a certificate for each client which will connect. The javax.net.ssl.trustStore and javax.net.ssl.trustStorePassword need to be set in addition to the properties above. Example sqlf server start -J-Djavax.net.ssl.keyStore=serverKeyStore.key \ -J-Djavax.net.ssl.keyStorePassword=qwerty \ -J-Djavax.net.ssl.trustStore=serverTrustStore.key \ -J-Djavax.net.ssl.trustStorePassword=qwerty \ -sqlfire.drda.sslMode=peerAuthentication Run a Client with SSL/TLS You enable basic SSL encryption on the client by the URL attribute ssl, the property ssl, or the datasource attribute ssl set to basic. Example Connection c = getConnection("jdbc:sqlfire://myhost:1527/db;ssl=basic"); Running a Client that Authenticates the Server For a client to authenticate the server, the client's trust store must contain the server's certificate. You enable client SSL with server authentication by setting the URL attribute ssl or the property ssl to peerAuthentication. In addition, the system properties javax.net.ssl.trustStore and javax.net.ssl.trustStorePassword need to be set. Example System.setProperty("javax.net.ssl.trustStore","clientTrustStore.key"); System.setProperty("javax.net.ssl.trustStorePassword","qwerty"); Connection c = getConnection("jdbc:sqlfire://myhost:1527/db;ssl=peerAuthentication"); Running the Client When the Server Does Client Authentication If the server authenticates clients, the client needs a key pair and a client certificate which is installed in the server's trust store. See Generate Key Pairs and Certificates on page 263. The client needs to set javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword. 265 Deploying vFabric SQLFire Example System.setProperty("javax.net.ssl.keyStore","clientKeyStore.key"); System.setProperty("javax.net.ssl.keyStorePassword","qwerty"); Connection c = getConnection("jdbc:sqlfire://myhost:1527/db;ssl=basic"); Running the Client When Both Parties Do Peer Authentication This is a combination of the two last variants. Example System.setProperty("javax.net.ssl.keyStore","clientKeyStore.key"); System.setProperty("javax.net.ssl.keyStorePassword","qwerty"); System.setProperty("javax.net.ssl.trustStore","clientTrustStore.key"); System.setProperty("javax.net.ssl.trustStorePassword","qwerty"); Connection c = getConnection("jdbc:sqlfire://myhost:1527/db;ssl=peerAuthentication"); 266 vFabric SQLFire User's Guide Part 8 Managing and Monitoring vFabric SQLFire Managing and Monitoring vFabric SQLFire describes how to use log files, system tables, and statistical data to understand the behavior of SQLFire deployment. This guide also provides general guidelines for tuning the performance of SQLFire members, applications, and individual queries. Topics: • • • • • • • • Configuring and Using SQLFire Log Files Querying SQLFire System Tables and Indexes Evaluating Query Plans and Query Statistics Overriding Optimizer Choices Evaluating System and Application Performance Using Java Management Extensions (JMX) Best Practices for Tuning Performance Detecting and Handling Network Segmentation ("Split Brain") 267 Chapter 43 Configuring and Using SQLFire Log Files By default SQLFire creates a log file named sqlfserver.log in the current directory when you start a server programmatically or using the sqlf utility. SQLFire creates a log file named sqlflocator.log in the current working directory when you start a locator. You can specify the name and location of the log file by using the JDBC boot property log-file when you start a server or locator. For example: sqlf server start -log-file=/home/user1/log/mysqlflog.log Log Message Format Each message in a server or locator log file contains the severity level, timestamp, and other important information. A SQLFire log message contains: • Severity level of the message. • Time that the message was logged. • ID of the thread that logged the message. • Body of the log message, which can be a string and/or an exception that includes the exception stack trace. The following shows an example log entry. [config 2011/05/24 17:19:45.705 IST
tid=0x1] This VM is setup with SQLFire datastore role. Severity Levels You can configure the logging system to record only those messages that are at or above a specified logging level. By default, the logging level is set to "config", which means that the system logs messages at config, info, warning, error, and severe severity levels. If you are having problems with your system, first lower the log-level (recording more of detailed messages to the log file) and recreate the problem. The additional log messages often help uncover the source. To specify the logging level, use the log-level property when you start a SQLFire server or locator. For example, to record all messages at log level "warning," "error," or "severe:" sqlf server start -log-file=/home/user1/log/mysqlflog.log -log-level=warning The table shows log levels from highest to lowest severity. 269 Managing and Monitoring vFabric SQLFire Log Level Indication severe Highest severity level, indicating a serious failure that usually prevents normal program execution. You may need to shut down or restart part of your cluster to correct the problem. error The operation indicated in the error message has failed. The server or locator should continue to run. warning Potential problem with the system. In general, warning messages describe events that are of interest to end users or system managers. info Informational messages for end users and system administrators. config Default severity level for logging messages. This log level provides static configuration messages that you can use to debug configuration problems. fine Tracing information that is generally of interest only to application developers. This logging level may generate lots of "noise" that might not indicate a problem in your application. It creates very verbose logs that may require significantly more disk space than logs that record only higher severity levels. Do not use this log setting unless you are asked to do so by VMware Support. finer, finest, and all Reserved for internal use. These log levels produce a large amount of data and consume large amounts of disk space and system resources. Do not use these settings unless you are asked to do so by VMware Support. Using java.util.logging.Logger for Application Log Messages Applications that use the SQLFire JDBC peer driver can log messages through the java.util.Logger logging API. You can obtain a handle to the java.util.Logger logger object by entering com.vmware.sqlfire after the application connects to the SQLFire cluster with the peer driver. For example: import java.util.logging.Logger; Logger logger = Logger.getLogger("com.vmware.sqlfire"); logger.info("Connected to a SQLFire system"); Using Trace Flags for Advanced Debugging SQLFire provides debug trace flags to record additional information about SQLFire features in the log file. SQLFire provides these trace flags that you can use with the sqlfire.debug.true system property to log additional details about SQLFire behavior: 270 Trace flag Enables QueryDistribution Detailed logging for distributed queries and DML statements, including information about message distribution to SQLFire members and scan types that were opened. StatementMatching Logging for optimizations that are related to unprepared statements. TraceAuthentication Additional logging for SQLFire authentication. TraceDBSynchronizer DBSynchronizer and WAN distribution logging. vFabric SQLFire User's Guide Configuring and Using SQLFire Log Files Trace flag Enables TraceClientConn Client-side connection open and close stack traces. TraceClientStatement Client-side, basic timing logging. TraceClientStatementMillis Client-side wall clock timing. TraceIndex Detailed index logging. TraceJars Logging for JAR installation, replace, and remove events. TraceTran Detailed logging for transaction events and operations, including commit and rollback. TraceLock_* Locking and unlocking information for all internal locks. TraceLock_DD Logging for all DataDictionary and table locks that are acquired or released. If you are asked to set a trace flag in a SQLFire member for debugging purposes, do so using the sqlfire.debug.true system property when you start a server or locator. For example, this command sets both the QueryDistribution and TraceIndex flags: sqlf server start -J-Dsqlfire.debug.true=QueryDistribution,TraceIndex For applications that use the JDBC peer driver, set trace-related flags in the sqlfire.debug.true system property before the application connects to the SQLFire cluster. For example, this code sets traces for index and query distribution and then connects using the peer driver: Properties props = new Properties(); props.put("sqlfire.debug.true", "TraceIndex,QueryDistribution"); System.setProperties(props); Java.sql.Connection conn = java.sql.DriverManager.getConnection("jdbc:sqlfire:"); Client-side trace flags write additional information to the client log file, which is configured using the log-file property. If you need to set a trace flag in a running system, use the SYS.SET_TRACE_FLAG system procedure. The procedure sets the trace flag in all members of the distributed system, including locators. You must execute the procedure as a system user. For example: sqlf> call sys.set_trace_flag('traceindex', 'true'); Statement executed. 271 Chapter 44 Querying SQLFire System Tables and Indexes You can monitor a SQLFire distributed system through SQL commands (Views and system procedures) and also through the GemStone Visual Statistics Display - a graphical tool to monitor statistics captured by each member in real-time or to chart historical statistics. See Using VSD to Analyze Statistics on page 292. You can also use the sqlf command-line tool, or any third party tool like SQuirreL. All monitored information from SQL commands can also be scripted using the sqlf tool. And, all captured statistics are also accessible from a script using the sqlf command. Getting Information About SQLFire Members The SYS.MEMBERS table provides information about all peers and servers that make up a SQLFire distributed system. You can use different queries to obtain details about individual members and their role in the cluster. • Determining Cluster Membership on page 273 • Determining Server Group Membership on page 274 Determining Cluster Membership To display a list of all members that participate in a given cluster, simply query all ID entries in sys.members. For example: select ID from SYS.MEMBERS; ID ------------------------------------vmc-ssrc-rh154(21046):42445/43015 vmc-ssrc-rh156(18283):28299/41236 vmc-ssrc-rh154(21045):15459/55080 vmc-ssrc-rh156(18284):43070/57131 vmc-ssrc-rh156(18285):23603/44410 vmc-ssrc-rh154(20904):11368/40245 6 rows selected The number of rows returned corresponds to the total number of peers, servers, and locators in the cluster. To determine each member's role in the system, include the KIND column in the query: select ID, KIND from SYS.MEMBERS; ID |KIND ------------------------------------------------------------vmc-ssrc-rh154(26615):31141/53707 |accessor(normal) vmc-ssrc-rh154(26739):9287/48842 |datastore(norma& 273 Managing and Monitoring vFabric SQLFire vmc-ssrc-rh156(23870):23802/60824 vmc-ssrc-rh154(26751):42054/49195 vmc-ssrc-rh156(23897):37163/43747 vmc-ssrc-rh156(23882):26779/35052 |datastore(norma& |datastore(norma& |datastore(norma& |accessor(normal) 6 rows selected Data store members host data in the cluster, while accessor members do not host data. This role is determined by the host-data boot property. If a cluster contains only a single data store, its KIND is listed as "datastore(loner)." Determining Server Group Membership SQLFire peers and servers that host data can participate in one or more server groups. You can use server group membership to specify how individual tables are partitioned or replicated across the cluster. You can also use server groups to target event listeners and other SQLFire features. To display the server group membership for each cluster member, query the SERVERGROUPS column. For example: select ID, SERVERGROUPS from SYS.MEMBERS; ID |SERVERGROUPS ---------------------------------------------------------vmc-ssrc-rh154(26615):31141/53707 | vmc-ssrc-rh154(26739):9287/48842 |SG2 vmc-ssrc-rh156(23897):37163/43747 |SG1 vmc-ssrc-rh156(23882):26779/35052 |SG1 vmc-ssrc-rh156(23870):23802/60824 |SG2 vmc-ssrc-rh154(26751):42054/49195 |SG1 6 rows selected Data stores that you start without specifying a server group name are added to the default server group, and have a null value for the SERVERGROUPS column. As an alternative, you use the GROUPSINTERSECT function to determine which members are part of the server group(s) that you specify in the function. Note that if you specify a comma-separated list, GROUPSINTERSECT requires the list to be sorted. For example: select ID, SERVERGROUPS from SYS.MEMBERS where GROUPSINTERSECT(SERVERGROUPS, 'SG1,SG2'); ID |SERVERGROUPS -----------------------------------------------------------------------vmc-ssrc-rh156(23897):37163/43747 |SG1 vmc-ssrc-rh154(26751):42054/49195 |SG1 vmc-ssrc-rh156(23882):26779/35052 |SG1 vmc-ssrc-rh156(23870):23802/60824 |SG2 vmc-ssrc-rh154(26739):9287/48842 |SG2 5 rows selected Getting Information About User Tables The SYS.SYSTABLES table provides information about all tables that are created in a SQLFire distributed system. You can use different queries to obtain details about tables and the server groups that host those tables. • Displaying a List of Tables on page 274 • Determining Where Data Is Stored on page 276 • Determining Whether a Table Is Replicated or Partitioned on page 277 • Determining How Persistent Data Is Stored on page 277 • Displaying Eviction Settings on page 278 274 vFabric SQLFire User's Guide Querying SQLFire System Tables and Indexes • Displaying Indexes on page 278 • Display Installed AsyncEventListeners on page 278 Displaying a List of Tables To display a list of all tables in the cluster: select TABLESCHEMANAME, TABLENAME from SYS.SYSTABLES order by TABLESCHEMANAME; TABLESCHEMANAME |TABLENAME ----------------------------------------------APP |PIZZA_ORDER_PIZZAS APP |PIZZA APP |TOPPING APP |PIZZA_ORDER APP |HIBERNATE_SEQUENCES APP |HOTEL APP |BASE APP |PIZZA_TOPPINGS APP |BOOKING APP |CUSTOMER SYS |SYSCONSTRAINTS SYS |ASYNCEVENTLISTENERS SYS |SYSCOLPERMS SYS |SYSKEYS SYS |SYSFILES SYS |SYSCONGLOMERATES SYS |SYSDEPENDS SYS |SYSROUTINEPERMS SYS |SYSTRIGGERS SYS |SYSTABLES SYS |SYSALIASES SYS |SYSROLES SYS |SYSDISKSTORES SYS |SYSVIEWS 275 Managing and Monitoring vFabric SQLFire SYS |SYSSTATISTICS SYS |SYSCOLUMNS SYS |SYSCHECKS SYS |GATEWAYSENDERS SYS |SYSFOREIGNKEYS SYS |SYSSCHEMAS SYS |SYSTABLEPERMS SYS |SYSSTATEMENTS SYSIBM |SYSDUMMY1 SYSSTAT |SYSXPLAIN_SORT_PROPS SYSSTAT |SYSXPLAIN_DIST_PROPS SYSSTAT |SYSXPLAIN_STATEMENTS SYSSTAT |SYSXPLAIN_RESULTSET_TIMINGS SYSSTAT |SYSXPLAIN_SCAN_PROPS SYSSTAT |SYSXPLAIN_STATEMENT_TIMINGS SYSSTAT |SYSXPLAIN_RESULTSETS 40 rows selected Determining Where Data Is Stored To determine which tables are deployed to a specific set of server groups: select TABLESCHEMANAME, TABLENAME from SYS.SYSTABLES where GROUPSINTERSECT(SERVERGROUPS, 'SG1,SG2'); TABLESCHEMANAME |TABLENAME -------------------------------------------------------------- 276 vFabric SQLFire User's Guide Querying SQLFire System Tables and Indexes APP APP APP APP |PIZZA_ORDER_PIZZAS |PIZZA_ORDER |BASE |PIZZA_TOPPINGS 4 rows selected For a specific table or set of tables, you can list all of the SQLFire members that host that table's data: select m.ID from SYS.SYSTABLES t, SYS.MEMBERS m where t.TABLESCHEMANAME='APP' and t.TABLENAME='PIZZA' and m.HOSTDATA = 1 and (LENGTH(t.SERVERGROUPS) = 0 or GROUPSINTERSECT(t.SERVERGROUPS, m.SERVERGROUPS)); ID ------------------------------------vmc-ssrc-rh156(23870):23802/60824 vmc-ssrc-rh154(26751):42054/49195 vmc-ssrc-rh156(23897):37163/43747 vmc-ssrc-rh154(26739):9287/48842 4 rows selected Determining Whether a Table Is Replicated or Partitioned The DATAPOLICY column specifies whether a table is replicated or partitioned, and whether a table is persisted to a disk store. For example: select TABLENAME, DATAPOLICY from SYS.SYSTABLES where TABLESCHEMANAME = 'APP'; TABLENAME |DATAPOLICY -------------------------------------------------PIZZA |PERSISTENT_REPLICATE PIZZA_ORDER_PIZZAS |PARTITION BASE |REPLICATE TOPPING |REPLICATE PIZZA_TOPPINGS |PARTITION PIZZA_ORDER |PERSISTENT_PARTITION 6 rows selected Determining How Persistent Data Is Stored For persistent tables, you can also display the disk store that persists the table's data, and whether the table uses synchronous or asynchronous persistence: select TABLENAME, DISKATTRS from SYS.SYSTABLES where TABLESCHEMANAME = 'APP'; TABLENAME |DISKATTRS ---------------------------------------------PIZZA |DiskStore is SQLF-DEFAULT-DISKSTORE; Synchronous writes to disk PIZZA_ORDER_PIZZAS |DiskStore is OVERFLOWDISKSTORE;Asynchronous writes to disk BASE |NULL TOPPING |NULL PIZZA_TOPPINGS |DiskStore is SQLF-DEFAULT-DISKSTORE; Synchronous writes to disk PIZZA_ORDER |DiskStore is SQLF-DEFAULT-DISKSTORE; Synchronous writes to disk 6 rows selected 277 Managing and Monitoring vFabric SQLFire Displaying Eviction Settings Use the EVICTIONATTRS column to determine if a table uses eviction settings and whether a table is configured to overflow to disk. For example: select TABLENAME, EVICTIONATTRS from SYS.SYSTABLES where TABLESCHEMANAME = 'APP'; TABLENAME |EVICTIONATTRS ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------PIZZA |NULL PIZZA_ORDER_PIZZAS | algorithm=lru-entry-count; action=overflow-to-disk; maximum=100 BASE |NULL TOPPING |NULL PIZZA_TOPPINGS | algorithm=lru-entry-count; action=overflow-to-disk; maximum=100 PIZZA_ORDER |NULL 6 rows selected Displaying Indexes Join SYSTABLES with CONGLOMERATENAME to determine if a table has an index and display the indexed columns. For example: select CONGLOMERATENAME from SYS.SYSCONGLOMERATES c, SYS.SYSTABLES t where c.ISINDEX = 1 and c.TABLEID = t.TABLEID and t.TABLESCHEMANAME = 'APP' and t.TABLENAME = 'PIZZA'; CONGLOMERATENAME ---------------2__PIZZA__ID 6__PIZZA__BASE 2 rows selected Displaying Installed AsyncEventListeners If you install AsyncEventListener implementations, you can join the SYSTABLES, MEMBERS, and ASYNCEVENTLISTENERS tables to display the listener implementations associated with a table as well as the data store ID on which the listener is installed: select t.*, m.ID DSID from SYS.SYSTABLES t, SYS.MEMBERS m, SYS.ASYNCEVENTLISTENERS a where t.tablename='
' and groupsintersect(a.SERVER_GROUPS, m.SERVERGROUPS) and groupsintersect(t.ASYNCLISTENERS, a.ID); See SYSTABLES on page 691 and ASYNCEVENTLISTENERS on page 669. 278 vFabric SQLFire User's Guide Chapter 45 Evaluating Query Plans and Query Statistics SQLFire can capture query execution plans to determine whether a given query will execute locally, or will execute in parallel across members of the cluster. You can also use query execution plans to determine where the system spends time in executing a particular query. You can generate Query plans on any peer or thin client connection that enables query plans. Capture a Query Plan for an Individual Statement SQLFire provides the EXPLAIN command to display the query execution plan for a single statement. Procedure 1. Establish a peer client connection to the SQLFire cluster. For example: sqlf connect peer 'host-data=false;mcast-port=12777'; 2. Increase the sqlf maximum display width in order to show the full query plan output. For example: sqlf> maximumdisplaywidth 10000; 3. Use the EXPLAIN command with a SQL statement to capture the query execution plan for that statement. For example: explain select * from flights f, flightavailability fa where f.flight_id = fa.flight_id; Note: If you did not increase the default MAXIMUMDISPLAYWIDTH value, the EXPLAIN play output is truncated before a stored in SYS.STATEMENTPLANS) of the plan you just created. For example: sqlf> select STMT_ID, STMT_TEXT from SYS.STATEMENTPLANS; STMT_ID |STMT_TEXT ----------------------------------------------------------------------------------00000001-ffff-ffff-ffff-000000000022| select * from flights f, flightavailability f 1 row selected sqlf> explain '00000001-ffff-ffff-ffff-000000000022'; You must connect using a peer client connection to view captured query plans. See Example Query Plan Analysis on page 280 for an example that describes the query plan output. 279 Managing and Monitoring vFabric SQLFire See Query Plan Codes on page 284 for information about individual codes displayed in the query plan output. Capture Query Plans for All Statements As an alternative to using the EXPLAIN command, you can use built-in system procedures to enable and disable query execution plan and statistics capture for all statements that you execute on a connection. Procedure 1. Establish a peer client or thin client connection to the SQLFire cluster. For example: sqlf connect peer 'host-data=false;mcast-port=12777'; 2. Use the SYSCS_UTIL.SET_EXPLAIN_CONNECTION procedure to begin capturing query execution plans for queries on this connection: call SYSCS_UTIL.SET_EXPLAIN_CONNECTION(1); 3. Use the SYSCS_UTIL.SET_STATISTICS_TIMING procedure to also capture query statistics information at a specified interval. For example: call SYSCS_UTIL.SET_STATISTICS_TIMING(1); 4. Execute the queries of interest and step through the result set of each query. 5. To disable query plan capture: call SYSCS_UTIL.SET_EXPLAIN_CONNECTION(0); call SYSCS_UTIL.SET_STATISTICS_TIMING(0); After you have captured query execution plans, you can use a peer client connection to query the captured plans. Example Query Plan Analysis This example uses the installed ToursDB database to explain how to analyze basic query plans in SQLFire. To follow along with this example, you must have access to a vFabric SQLFire installation and the ToursDB scripts in the quickstart subdirectory. 1. Set your PATH environment variable to include the bin subdirectory of the SQLFire installation. 2. Start a single SQLFire server. For example: mkdir query-plan-example cd query-plan-example sqlf server start 3. Change to the quickstart subdirectory of your SQLFire installation: cd ~/vFabric_SQLFire_11_bNNNNN/quickstart 4. Connect to the server as a peer, and execute the scripts to create the sample database: sqlf connect peer 'host-data=false;mcast-port=10334'; run 'ToursDB_schema.sql'; run 'loadTables.sql'; 5. Increase the sqlf maximum display width in order to show the full query plan output: maximumdisplaywidth 10000; 280 vFabric SQLFire User's Guide Evaluating Query Plans and Query Statistics 6. Execute the EXPLAIN command with the following query: explain select * from flights f, flightavailability fa where f.flight_id=fa.flight_id and f.flight_id='AA1116'; You receive output similar to: MEMBER_PLAN -------------------------------------------------------------------------------------------------------------------------------ORIGINATOR curwen(26762):24929 BEGIN TIME 2013-06-14 14:36:37.17 END TIME 2013-06-14 14:36:37.231 DISTRIBUTION to 1 members took 341 microseconds ( message sending min/max/avg time 369/369/369 microseconds and receiving min/max/avg time 278/278/278 microseconds ) SEQUENTIAL-ITERATION of 14 rows took 1963 microseconds Slowest Member Plan: member curwen(26758):2779 begin_execution 2013-06-14 14:36:37.173 end_execution 2013-06-14 14:36:37.223 QUERY-RECEIVE execute_time 50.542 ms member_node curwen(26762):24929 RESULT-SEND execute_time 0.055 ms member_node curwen(26762):24929 RESULT-HOLDER execute_time 3.001 ms returned_rows 14 no_opens 1 NLJOIN (2.32%) execute_time 0.428 ms returned_rows 14 no_opens 1 TABLESCAN (51.16%) execute_time 9.426 ms returned_rows 1 no_opens 1 scan_qualifiers Column[0][0] Id: FLIGHT_ID Operator: = AA1116 Ordered nulls: false Unknown return value: false scanned_object APP.FLIGHTS scan_type HEAP ROWIDSCAN (1.11%) execute_time 0.206 ms returned_rows 14 no_opens 1 node_details FLIGHTAVAILABILITY : CONSTRAINTSCAN (45.39%) execute_time 8.362 ms returned_rows 14 no_opens 1 scan_qualifiers None scanned_object APP.6__FLIGHTAVAILABILITY__FLIGHT_ID__SEGMENT_NUMBER:base-table:APP.FLIGHTAVAILABILITY scan_type node_details WHERE : ((F.FLIGHT_ID = FA.FLIGHT_ID) and true) Fastest Member Plan: member curwen(26758):2779 begin_execution 2013-06-14 14:36:37.173 end_execution 2013-06-14 14:36:37.223 QUERY-RECEIVE execute_time 50.542 ms member_node curwen(26762):24929 RESULT-SEND execute_time 0.055 ms member_node curwen(26762):24929 RESULT-HOLDER execute_time 3.001 ms returned_rows 14 no_opens 1 NLJOIN (2.32%) execute_time 0.428 ms returned_rows 14 no_opens 1 TABLESCAN (51.16%) execute_time 9.426 ms returned_rows 1 no_opens 1 scan_qualifiers Column[0][0] Id: FLIGHT_ID Operator: = AA1116 Ordered nulls: false Unknown return value: false scanned_object APP.FLIGHTS scan_type HEAP ROWIDSCAN (1.11%) execute_time 0.206 ms returned_rows 14 no_opens 281 Managing and Monitoring vFabric SQLFire 1 node_details FLIGHTAVAILABILITY : CONSTRAINTSCAN (45.39%) execute_time 8.362 ms returned_rows 14 no_opens 1 scan_qualifiers None scanned_object APP.6__FLIGHTAVAILABILITY__FLIGHT_ID__SEGMENT_NUMBER:base-table:APP.FLIGHTAVAILABILITY scan_type node_details WHERE : ((F.FLIGHT_ID = FA.FLIGHT_ID) and true) 3 rows selected In this example, the query is distributed from the peer client (the ORIGINATOR) to the single data store in the cluster. As there is only one data store member in the cluster, the fastest and slowest plans reported in the output refer to the same plan (the same information is repeated) in both sections. The body of a SQLFire query plan is divided into two main sections identified by the query plan codes QUERY-SCATTER and QUERY-RECEIVE. Each section contains indented rows showing nested tasks. Because each task feeds into the task above it, you should read the query plan starting with the bottom, most-nested task in each section. Individual task rows show the task execution time in milliseconds, as well as the overall percentage of time spent completing that task relative to all of the tasks in the section, combined. QUERY-SCATTER is displayed only when you use the EXPLAIN stmt_id syntax (it does not appear in the above output). QUERY-SCATTER includes all of the tasks associated with delivering the query from the query coordinator to one or more data stores in the cluster, and then receiving and processing results on the query coordinator. This example uses a single data store member to provide all results, so very little time is spent on the query coordinator. When data is distributed across multiple data stores (for partitioned and/or replicated tables) additional time will be spent on the query coordinator to merge the results from each data store. The QUERY-RECEIVE section of the plan describes the query processing tasks that a data store member takes in order to execute a query. This header displays the member ID and process ID of the data store, as well as the total aggregate time for all of the subordinate tasks. If the query is distributed to multiple data store members, then each member will display a separate QUERY-RECEIVE section. Each section should be identical, unless tables are partitioned across different sets of machines of VMs. The example shows that a nested loop join (NLJOIN) is performed in order to produce the results. NLJOIN always has two nested subtasks that represent the outer and inner tables in the join. In this example, a TABLESCAN is first performed on the FLIGHTS table, which holds the foreign key FLIGHT_ID. The TABLESCAN returns a single row. The inner table then uses the results of the TABLESCAN in a CONSTRAINTSCAN performed on the FLIGHTAVAILABILITY table. Table scans are very expensive operations in query processing, and even this quick query of a small data set shows that the majority of the time (51% of the query execution time) was spent scanning the FLIGHTS table. The remaining steps show how creating an index changes the query plan and improves performance. 7. To avoid the costly table scan used in the sample query, execute the following command to create an index on the FLIGHT_ID column of the FLIGHTS table: CREATE INDEX fa_index ON flights (flight_id); 8. Re-run the query, creating a new query plan. Then examine the new plan: explain select * from flights f, flightavailability fa where f.flight_id=fa.flight_id and f.flight_id='AA1116'; You should receive output similar to: MEMBER_PLAN -------------------------------------------------------------------------------------------------------------------------------ORIGINATOR curwen(26888):47762 BEGIN TIME 2013-06-14 14:54:20.852 282 vFabric SQLFire User's Guide Evaluating Query Plans and Query Statistics END TIME 2013-06-14 14:54:20.87 DISTRIBUTION to 1 members took 227 microseconds ( message sending min/max/avg time 225/225/225 microseconds and receiving min/max/avg time 79/79/79 microseconds ) SEQUENTIAL-ITERATION of 14 rows took 581 microseconds Slowest Member Plan: member curwen(26884):27256 begin_execution 2013-06-14 14:54:20.852 end_execution 2013-06-14 14:54:20.865 QUERY-RECEIVE execute_time 12.342 ms member_node curwen(26888):47762 RESULT-SEND execute_time 0.023 ms member_node curwen(26888):47762 RESULT-HOLDER execute_time 1.105 ms returned_rows 14 no_opens 1 NLJOIN (15.22%) execute_time 0.245 ms returned_rows 14 no_opens 1 ROWIDSCAN (2.54%) execute_time 0.041 ms returned_rows 1 no_opens 1 node_details FLIGHTS : INDEXSCAN (35.98%) execute_time 0.579 ms returned_rows 1 no_opens 1 scan_qualifiers None scanned_object FA_INDEX scan_type node_details WHERE : ((F.FLIGHT_ID = CONSTANT:AA1116) and true) ROWIDSCAN (6.77%) execute_time 0.109 ms returned_rows 14 no_opens 1 node_details FLIGHTAVAILABILITY : CONSTRAINTSCAN (39.46%) execute_time 0.635 ms returned_rows 14 no_opens 1 scan_qualifiers None scanned_object APP.6__FLIGHTAVAILABILITY__FLIGHT_ID__SEGMENT_NUMBER:base-table:APP.FLIGHTAVAILABILITY scan_type node_details WHERE : ((F.FLIGHT_ID = FA.FLIGHT_ID) and true) Fastest Member Plan: member curwen(26884):27256 begin_execution 2013-06-14 14:54:20.852 end_execution 2013-06-14 14:54:20.865 QUERY-RECEIVE execute_time 12.342 ms member_node curwen(26888):47762 RESULT-SEND execute_time 0.023 ms member_node curwen(26888):47762 RESULT-HOLDER execute_time 1.105 ms returned_rows 14 no_opens 1 NLJOIN (15.22%) execute_time 0.245 ms returned_rows 14 no_opens 1 ROWIDSCAN (2.54%) execute_time 0.041 ms returned_rows 1 no_opens 1 node_details FLIGHTS : INDEXSCAN (35.98%) execute_time 0.579 ms returned_rows 1 no_opens 1 scan_qualifiers None scanned_object FA_INDEX scan_type node_details WHERE : ((F.FLIGHT_ID = CONSTANT:AA1116) and true) ROWIDSCAN (6.77%) execute_time 0.109 ms returned_rows 14 no_opens 1 node_details FLIGHTAVAILABILITY : CONSTRAINTSCAN (39.46%) execute_time 0.635 ms returned_rows 14 no_opens 1 scan_qualifiers None scanned_object APP.6__FLIGHTAVAILABILITY__FLIGHT_ID__SEGMENT_NUMBER:base-table:APP.FLIGHTAVAILABILITY 283 Managing and Monitoring vFabric SQLFire scan_type node_details WHERE : ((F.FLIGHT_ID = FA.FLIGHT_ID) and true) 3 rows selected You can see that the table scan is now replaced by a more efficient INDEXSCAN task in the join. Although the query on the original, unindexed table completed very quickly, note that the index scan took less than a millisecond to complete, whereas the original table scan required over 9 milliseconds. This performance improvement is magnified as the number of rows increases, so always ensure that indexes are used when possible for long-running queries. Query Plan Codes SQLFire may add the following codes to a generated query plan. All times reported in the plan are in milliseconds. The following codes apply to the query coordinator (the SQLFire member that distributes a query to other data store members and processes the results). 284 Query Plan Code Description DISTRIBUTION-END The total time spent processing the query on the data store members. GROUPED-ITERATION The time spent grouping rows on the query coordinator. This code is displayed only if the query contains an GROUP BY clause and the query was processed over multiple table partitions. ORDERED-ITERATION The time spent resorting rows on the query coordinator. This code is displayed only if the query contains an ORDER BY clause and the query was processed over multiple table partitions. OUTER-JOIN-ITERATION The time spent evaluating outer joins after receiving rows from other members. QUERY-SCATTER QUERY-SCATTER is the top-level code that organizes all tasks associated with sending queries from the query coordinator and receiving and processing results on the coordinator. The execute time reported for QUERY-SCATTER is the total, aggregate time of all the subordinate tasks. QUERY-SCATTER lists the SQLFire members to which the query was distributed; it does not list the query coordinator member. QUERY-SEND The network time required to send the query, as well as the target member. This is an "OUT" operation from the perspective of the query coordinator. A separate QUERY-SEND code is displayed for each data store that receives the query. REGION-GET An atomic "get" operation in the GemFire component. REGION-GETALL An atomic "getall" operation in the GemFire component. REGION-PUT An atomic "put" operation in the GemFire component. REGION-PUTALL An atomic "putall" operation in the GemFire component. RESULT-RECEIVE The network time required to receive the results from data stores back to the query coordinator. This is an "IN" operation from the perspective of the query coordinator. A separate RESULT-RECEIVE code is displayed for each data store that processes the query. RESULT-HOLDER Shows the total time spent batching up results from the target member. This is an "IN" operation from the perspective of the query coordinator. RESULT-HOLDER displays the number of rows returned from the specified data store member. A separate RESULT-HOLDER code is displayed for each data store that processes the query. vFabric SQLFire User's Guide Evaluating Query Plans and Query Statistics Query Plan Code Description RESULT-HOLDER is a blocking operation that is connected to SEQUENTIAL-ITERATION. ROUNDROBIN-ITERATION The time required to merge results from an n-way merge. ROW-COUNT-ITERATION The time spent returning rows specified in a FETCH NEXT clause. (See OFFSET and FETCH FIRST Clauses on page 549.) SEQUENTIAL-ITERATION SEQUENTIAL-ITERATION is an operator that gathers results and sends them to the client as the client requests, one block at a time. This code shows the total aggregate row count of the query. If a FETCH FIRST clause was used, it is displayed in this operator. The following codes are shown only for data store members in a query plan: Query Plan Code Description AGGREGATION An aggregate operation such as SUM, AVG, MIN, or MAX. CONSTRAINTSCAN The time spent on an index scan created from a table constraint. EXCEPT An EXCEPT, EXCEPT ALL, or EXCEPT DISTINCT operation. See SQL Language Limitations on page 765. FILTER A predicate filtering operation. GLOBALINDEXSCAN The time spent performing a global hash index scan (for example, for reference checks). GROUPBY Time spent grouping columns. HASHJOIN The time spent on a hash join operation. HASHSCAN The time spent scanning a generated hash table. HEAP Time spent scanning GemFire regions. INDEXSCAN If the query required a scan on an index, then this code indicates the time required for the scan. INTERSECT An INTERSECT, INTERSECT ALL, or INTERSECT DISTINCT operation. See SQL Language Limitations on page 765. LOHASHJOIN The time spend for a left or right hash outer join operation. LONLJOIN The time spend for a left or right nested loop outer join operation. MERGEJOIN The time spent on a merge join operation. NLJOIN The time taken to perform a nested loop join (matching all of the left table rows with the right table rows in a query). NLJOIN always has two nested entries. The first entry corresponds to the outer table, which is read once and returns some number (n) of rows. The second entry corresponds to the inner table which is iterated over n times (once for each result in the outer table). The individual seeks for the inner and outer tables are timed separately and are listed in each nested entry. Example Query Plan Analysis on page 280 describes an example query plan that performs an NLJOIN. PROJECT-FILTER A predicate filtering operation that occurs while extracting columns (PROJECTION operation). PROJECTION The time spent to extract the selected columns from the base row of the table. This code can appear multiple times for a query depending on how the engine processes the query. QUERY-RECEIVE QUERY-RECEIVE is the top-level code that organizes all tasks associated with processing a query on a specific data store member. 285 Managing and Monitoring vFabric SQLFire Query Plan Code Description QUERY-RECEIVE displays the member ID and process ID of the data store, as well as the total aggregate time for all of the subordinate tasks. If the query was distributed to multiple data store members, then each member displays a separate QUERY-RECEIVE code. The contents of multiple QUERY-RECEIVE codes are similar unless tables are partitioned across different VMs or physical machines. 286 RESULT-HOLDER This value is linked to the RESULT-HOLDER code on the query coordinator. All of the tasks beneath RESULT-HOLDER represent query operators performed on the data store member. RESULT-SEND The network time that was spent sending result rows back to the query coordinator. The target node is the query coordinator. ROW-COUNT The time spent processing results for the FETCH clause. ROWIDSCAN The total time spent for index entries to fetch the base row from the table. This occurs when the projection of the query is different from the index column. SET Indicates a set operation (a UNION, UNION ALL, UNION DISTINCT, INTERSECT, INTERSECT ALL, INTERSECT DISTINCT, EXCEPT, EXCEPT ALL, or EXCEPT DISTINCT operation). See SQL Language Limitations on page 765. SCROLL-INSENSITIVE A scroll insensitive cursor operation. SORT The time spent sorting rows to execute an ORDER BY, DISTINCT, or GROUP BY clause. TABLESCAN The time required to scan a table. UNION The time spent performing a UNION, UNION ALL, or UNION DISTINCT operation of two queries. See SQL Language Limitations on page 765. vFabric SQLFire User's Guide Chapter 46 Overriding Optimizer Choices You can override the default behavior of the SQLFire query optimizer by including a -- SQLFIRE-PROPERTIES clause and a property definition in a SQL statement. The clause and property definition both appear within the context of a SQL comment (beginning with two dashes "--"). Because optimizer properties are expressed as comments, they must appear at the end of a line. If you want to continue the SQL statement after including a property definition, enter a newline character (\n) before continuing the statement. This rule applies to the terminating semicolon, if the optimizer hint appears at the end of the SQL statement. Note: When processing a SQL script file, SQLFire does not recognize other parts of a SQL statement if they appear at the end of a SQL comment line. For this reason, you must place any remaining parts of the SQL statement on a separate line. This includes the terminating semicolon, if an optimizer hint extends to the end of the statement. SQLFire supports two general categories of properties: • FROM clause properties—These property definitions must be specified between a query's FROM clause and the first table name: FROM [ -- SQLFIRE-PROPERTIES fromProperty = value \n ] TableExpression [, TableExpression ]* • Table properties—These properties apply to the preceding base table, and the property definition must appear at the end of the TableExpression (immediately after the base table name or alias, and before any addition table name, JOIN clause, or comma): { table-name | view-name } [ [ AS ] correlation-Name [ ( simple-column-name [ , simple-column-name ]* ) ] ] [ -- SQLFIRE-PROPERTIES tableProperty = value ] The space between -- and SQLFIRE-PROPERTIES is optional. Note: Make sure that you adhere to the correct syntax when using the -- SQLFIRE-PROPERTIES clause. Failure to do so can cause the parser to interpret it as a comment and ignore it. Note: SQLFire also provides optimizer properties that are only used when querying the MEMORYANALYTICS on page 675. See Estimating Memory Requirements on page 79. The following FROM clause and table properties are supported. 287 Managing and Monitoring vFabric SQLFire Property Name Type Description constraint Table property To force the use of the index that enforces a primary key, a foreign key, or unique constraint, use the constraint property and specify the unqualified name of the constraint. The constraint property can be used only within a TableExpression, and it can be specified only on base tables; it cannot be specified on views or derived tables. index Table property The index property is similar to the constraint property. To force use of a particular index, specify the unqualified index name. To force a table scan, specify null for the index name. The index property can be used only within a TableExpression, and it can be specified only on base tables; it cannot be specified on views or derived tables. joinOrder FROM clause property Use the joinOrder property to override the optimizer's choice of join order for two tables. When the value FIXED is specified, the optimizer will choose the order of tables as they appear in the FROM clause as the join order. Valid values for the joinOrder property include FIXED and UNFIXED. The joinOrder property can be used with a FROM clause. joinStrategy Table property Use the joinStrategy property to override the optimizer's choice of join strategy. The two types of join strategy are called nested loop and hash. In a nested loop join strategy, for each qualifying row in the outer table, SQLFire uses the appropriate access path (index or table scan) to find the matching rows in the inner table. In a hash join strategy, SQLFire constructs a hash table that represents the inner table. For each qualifying row in the outer table, SQLFire does a quick lookup on the hash table to find the matching rows in the inner table. SQLFire needs to scan the inner table or index only once to create the hash table. The -SQLFIRE-PROPERTIES parameter must immediately follow the inner table. Typically, you will use the joinStrategy property only in conjunction with the joinOrder property. Specifying a join strategy without knowing the join order can result in less-than-optimal performance. Valid values include HASH and NESTEDLOOP. The joinStrategy property can be used only within a TableExpression. 288 vFabric SQLFire User's Guide Overriding Optimizer Choices Property Name Type Description statementAlias FROM clause property Use this property to create an alias for a user query. When using the Visual Statistics Display (VSD), SQLFire displays the alias name instead of the original, system-generated statement alias. See Using VSD to Analyze Statistics on page 292. Note: You cannot include whitespace characters as word separators in the alias name. withSecondaries Table property Use this property to include secondary buckets for a partitioned table when joining the table with a virtual table. When you set this property to TRUE, SQLFire considers secondary buckets for routing and scanning purposes when joining the partitioned table with a virtual table. When set to FALSE, secondary buckets are never considered in the query. Note: This table property can only be used with base tables or virtual tables. Examples The following examples illustrate the use of the -- SQLFIRE-PROPERTIES clause. Note that these examples show the newline character as \n to emphasize that any part of the SQL statement that continues beyond the optimizer hint must begin on a new line: constraint CREATE TABLE t1 (c1 int, c2 int, c3 int, CONSTRAINT cons1 PRIMARY KEY (c1, c2)); INSERT INTO t1 VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4); SELECT * FROM t1 -- SQLFIRE-PROPERTIES constraint=cons1 \n FOR UPDATE; index CREATE TABLE t1 (c1 int, c2 int, c3 int, CONSTRAINT cons1 PRIMARY KEY (c1, c2)); INSERT INTO t1 VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4); CREATE INDEX t1_c1 ON t1(c1); SELECT * FROM t1 -- SQLFIRE-PROPERTIES index=t1_c1 \n WHERE c1=1; joinOrder CREATE CREATE UNIQUE INSERT INSERT SELECT t1, t2 TABLE t1 (c1 int, c2 int, c3 int, CONSTRAINT cons1 PRIMARY KEY (c1, c2)); TABLE t2 (c1 int not null, c2 int not null, c3 int, CONSTRAINT cons2 (c1, c2)); INTO t1 VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4); INTO t2 VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4); * FROM -- SQLFIRE-PROPERTIES joinOrder=FIXED \n WHERE t1.c1=t2.c1; joinStrategy CREATE TABLE t1 (c1 int, c2 int, c3 int, CONSTRAINT cons1 PRIMARY KEY (c1, c2)); CREATE TABLE t2 (c1 int not null, c2 int not null, c3 int, CONSTRAINT cons2 289 Managing and Monitoring vFabric SQLFire UNIQUE (c1, c2)); INSERT INTO t1 VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4); INSERT INTO t2 VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4); SELECT * FROM -- SQLFIRE-PROPERTIES joinOrder=FIXED \n t1 a, t1 b -- SQLFIRE-PROPERTIES joinStrategy=NESTEDLOOP \n WHERE a.c1=b.c1; statementAlias With the following query, SQLFire uses that statement alias "My_QUERY" instead of a system-generated alias: SELECT * FROM -- SQLFIRE-PROPERTIES statementAlias=My_QUERY \n userTable t1 -- SQLFIRE-PROPERTIES index=IDX_COL1 \n WHERE t1.col1 is not null; withSecondaries This query considers secondary buckets when joining the partitioned table with sys.members: SELECT dsid(), count(1) from sys.members , userPartitionedTable t1 -SQLFIRE-PROPERTIES withSecondaries=true \n GROUP BY dsid(); withMemoryFootPrint This query displays the complete memory footprint of tables and indexes: SELECT * FROM sys.memoryAnalytics -- SQLFIRE-PROPERTIES sizerHints=withMemoryFootPrint \n ; 290 vFabric SQLFire User's Guide Chapter 47 Evaluating System and Application Performance SQLFire provides statistics for analyzing system performance. Any member of a distributed system, including SQLFire servers, locators, and peer clients, can collect and archive this statistical data. SQLFire samples statistics at a configurable interval and writes them to an archive. The archives can be read at any time, including at runtime. You can view and analyze runtime or archived historical data using these tools: • sqlf stats is a command-line tool provided with the SQLFire product. • VMware vFabric GemFire Visual Statistics Display (VSD) is a graphical tool that is installed in the tools/vsd subdirectory of the vFabric SQLFire installation. See Using VSD to Analyze Statistics on page 292. Note: SQLFire statistics use the Java System.nanoTimer for nanosecond timing. This method provides nanosecond precision, but not necessarily nanosecond accuracy. For more information, see the online Java documentation for System.nanoTimer for the JRE you are using with SQLFire. Note: Runtime viewing of statistics archives files is not necessarily real-time, because of file system buffering. Collecting System Statistics You can use enable SQLFire system statistics using either a system procedure, member boot properties, or connection properties. The SYS.SET_GLOBAL_STATEMENT_STATISTICS system procedure provides a simple way to enable or disable statistics collection for an entire SQLFire distributed system. The global setting applies to all members and client connections, and you can change the setting at any time. For example, the following command enables both statement-level statistics and time-based statistics: sys.set_global_statement_statistics(true, true); You can optionally enable statistics collection per-member using the boot properties: • statistic-sampling-enabled • enable-time-statistics These boot properties help you configure a member's statistic archive file location and size: • statistic-archive-file • archive-disk-space-limit • archive-file-size-limit 291 Managing and Monitoring vFabric SQLFire • statistic-sample-rate To collect statement-level statistics and time-based, statement-level statistics for a specific connection (rather than globally or per-member), use these connection properties with a peer client connection: • enable-stats • enable-timestats Note that enable-stats and enable-timestats can only be used with a peer client connect, and not with a thin client connection. Configuration Properties on page 327 describes these and other SQLFire configuration properties. Note: Because of the overhead required for taking many timestamps, it is recommended that you enable time-based statistics only during testing and debugging. Note: Use statement-level statistics only when the number of individual statements is small, such as when using prepared statements. SQLFire creates a separate statistics instance for each individual statement. With a large number of these statements, it can be difficult to load archives into VSD and navigate to those statistics of interest. Collecting Application Statistics You can collect your own application-defined statistics to record anything of interest to your application, such as throughput and latency for multi-statement transactions and application-specific configuration values. This capability gives you complete control over what to measure. It also makes it possible to gather statement-level or time-based statistics without the overhead of turning them on in the product. Any peer member of a SQLFire distributed system can collect and use application statistics. You can also use application statistics from non-members by connecting to a "loner" distributed system before defining statistics. Statistics in the VMware vFabric Gemfire documentation describes how to incorporate statistics in your application. Using VSD to Analyze Statistics The Visual Statistics Display (VSD) reads the sampled statistics from one or more archives and produces graphical displays for analysis. VSD is installed with vFabric SQLFire in the tools subdirectory. The statistics values (Y-axis) are plotted over time (X-axis). This makes it easy to see how statistics are trending, and to correlate different statistics. Start VSD by entering the command: /bin/vsd/bin/vsd Archives are usually loaded by passing them in on the command line: /bin/vsd/bin/vsd … VSD’s extensive online help offers complete reference information about the tool. The sections that follow show examples of analyzing the SQLFire performance metrics. Transaction Performance SQLFire provides statistics for transaction commits, rollbacks, and failures You can monitor SQLFire transactions with VSD. You can use these statistics to see the transaction rate. An example follows the table. 292 vFabric SQLFire User's Guide Evaluating System and Application Performance Type CachePerfStats Name cachePerfStats Statistic txCommits, txRollbacks Description The number of times a transaction has committed or rolled back. Type CachePerfStats Name cachePerfStats Statistic txSuccessLifeTime, txRollbackLifeTime Description The total time spent in a transaction that committed or rolled back. Example: Transaction Rate and Latency This VSD chart shows the aggregated transaction rate across three FabricServer instances, along with the rollback rate. With time statistics enabled, you can compute the average latency for each sample point as the total time spent in the transaction divided by the number of transactions in each sample. The chart also shows that the average latency across all samples is 6.76 ms. 293 Managing and Monitoring vFabric SQLFire Table Performance You can get an idea of the relative performance of inserts, updates, and selects by looking at the underlying statistics. An example follows the table. Type CachePerfStats Name RegionStats-
Statistic creates, puts, deletes Description Number of times that an entry is added to, replaced in, or read from the replicated table. Type CachePerfStats Name RegionStats-partition-
Statistic creates, puts, deletes Description Number of times that an entry is added to, replaced in, or read from the partitioned table. Example: Read and Write Performance These VSD charts show the rates of reads and writes to the various tables in the application. 294 vFabric SQLFire User's Guide Evaluating System and Application Performance You can use these statistics to see that the NEW_ORDER table is growing over time. After the initial orders are loaded, new orders are being placed (created) faster than customers are paying for (destroying) them. 295 Managing and Monitoring vFabric SQLFire SQL Statement Performance With statement-level statistics enabled, statistics are available for all DML statements. An example follows the table. Type StatementStats Name INSERT, SELECT, UPDATE, DELETE Statistic NumExecutesEnded Description The number of times that a statement was executed. Example: Prepared Statements This VSD chart shows statistics for two fabric servers for prepared statements that insert rows in the history table. The first round of inserts occurs during initial data loading. The second round occurs as part of normal business operations. This chart also shows that the application used different prepared statements for data loading and subsequent transactions, with slightly different ordering in the fields. If the statements had been identical, there would be only one instance per server. 296 vFabric SQLFire User's Guide Evaluating System and Application Performance Application Performance Using application-based statistics provides the most control over throughput and latency measurement. This type of measurement is possible in peer clients. An example follows. For more information, see Collecting Application Statistics. Example: Transactions Per Second with Multiple Clients The following VSD chart shows an application-defined statistic for the number of new order transactions executed per second, aggregated over 180 clients. Each new order transaction consists of many statement executions. The dip in throughput early on is caused by an application synchronization point. The next chart shows the instantaneous latency for the stock level transaction as the elapsed transaction time divided by the number of transactions for each sample. The average is 2.8 ms with a maximum of 7.18 ms. Each 297 Managing and Monitoring vFabric SQLFire sample represents many transactions, so each data point is averaged over all transactions in the sample. If the application needed a true maximum latency, it could keep track of that in a separate statistic. Memory Usage SQLFire provides statistics for system memory, JVM heap, garbage collection, and table sizes. You can use these statistics to analyze your application's memory usage. An example follows the table. 298 Type CachePerfStats Name RegionStats-
and RegsionStats-partition-
Statistic entries Description Number of rows in the replicated or partitioned table. Type PartitionedRegionStats Name PartitionedRegion//
Statistics Statistic dataStoreEntryCount and dataStoreBytesInUse Description Number of rows/bytes in a partitioned table, including redundant copies. Type VMMemoryUsageStats Name vmHeapMemoryStats Statistic usedMemory and maxMemory Description Used heap and maximum heap, in bytes. Type VMMemoryPoolStats Name ParSurvivorSpace, ParEdenSpace, CMSOldGen vFabric SQLFire User's Guide Evaluating System and Application Performance Statistic currentUsedMemory Description Estimated used memory, in bytes, for each heap memory pool. Type VMGCStats Name ParNew, ConcurrentMarkSweep Statistic collectionTime Description Approximate elapsed time that this garbage collector spent doing collections. Type LinuxSystemStats Name Statistic pagesSwappedIn, pagesSwappedOut Description Number of pages that have been brought into memory from disk or flushed out of memory to disk by the operating system. These paging operations seriously degrade performance. Example: Heap Usage This VSD chart shows the heap usage in a fabric server plotted against the entry counts in each of the replicated and partitioned tables used in an application. This suggests that heap is growing over time due to an increase in the number of rows in the ORDER_LINE table. Several associated tables are growing in size as well. This growth can be verified by looking at the bytes used by each of the partitioned tables. The ORDER_LINE table is responsible for most of the heap growth. 299 Managing and Monitoring vFabric SQLFire CPU Usage SQLFire provides host and JVM statistics for examining system load. An example follows the table. 300 Type LinuxSystemStats Name Statistic cpus Description Number of CPUs on this host. Type LinuxSystemStats Name Statistic cpuActive, cpuSystem, cpuUser Description Percentage of the total available time that has been used in a non-idle state, in system (kernel) code and in user code. This is aggregated across all CPUs. Type LinuxSystemStats Name Statistic loadAverage1, loadAverage5, loadAverage15 Description Average number of threads in the run queue or waiting for disk I/O over the last 1, 5, 15 minutes. Type VMStats Name vmStats Statistic processCpuTime Description CPU time, measured in nanoseconds, used by the process. vFabric SQLFire User's Guide Evaluating System and Application Performance Example: CPU Usage by System and User This VSD chart shows the CPU usage in a fabric server, and breaks it down into system and user. The majority of the time is spent in user code. The first few minutes correspond to loading various tables. The rest is the main workload, during which many clients are executing transactions. 301 Chapter 48 Using Java Management Extensions (JMX) You can use the Java Management Extensions (JMX) with vFabric SQLFire for additional administrative and monitoring capability Basic JMX monitoring can be tightly integrated into SQLFire member processes. You can configure either locators and/or servers to automatically start a JMX manager process if necessary when the member starts. As an alternative, if you need to provide HTTP access for monitoring SQLFire MBeans, you can run a standalone JMX agent with MX4J. Using a JMX Manager Node SQLFire's management and monitoring system consists of one JMX Manager node (there should only be one) and one or more managed nodes within a distributed system. All members in the distributed system use MBeans for certain management and monitoring functions. Managed Node Each member of a distributed system is a managed node. Any node that is not currently also acting as a JMX Manager node is referred to simply as a managed node. A managed node has the following resources so that it can answer JMX queries both locally and remotely: • An RMI connector that allows a remote JMX client to connect directly to the node and access all local MBeans. • Local MBeans that represent the locally monitored components on the node. • Built-in platform MBeans JMX Manager Node A JMX Manager node is a member that can manage other SQLFire members --that is, other managed nodes -as well as itself. A JMX Manager node can manage all other members in the distributed system. To convert a managed node to a JMX Manager node, you configure the SQLFire property jmx-manager=true, either in the sqlfire.properties file or on the command line when you start the member. The JMX Manager node has the following extra resources allocated so that it can answer JMX queries: • RMI connector that allows JMX clients to connect to and access all MBeans in the distributed system. • Local MBeans that represent the locally monitored components on this node, same as any other managed node. • Aggregate MBeans: • DistributedSystemMBean. • DistributedRegionMBean. • MemberGroupMBean. • DistributedLockServiceMBean 303 Managing and Monitoring vFabric SQLFire • ManagerMBean with Scope=ALL, which allows various distributed system-wide operations. • Proxy to MBeans on managed nodes. • Built-in platform MBeans. Starting a JMX Manager JMX Manager nodes are members that manage other SQLFire members (as well as themselves). A JMX Manager node can manage all other members in the distributed system. To convert a managed node to a JMX Manager you configure the SQLFire properties jmx-manager=true and jmx-manager-start=true in the sqlfire.properties file or on the command line when you start the member. To start a locator as a JMX Manager: sqlf locator start -jmx-manager=true -jmx-manager-start=true A server can also become a JMX Manager when started. However, you should only have one JMX Manager per distributed system. After the member becomes a JMX Manager, all other jmx-manager-* configuration properties listed in Configuring a JMX Manager are applied. Configuring a JMX Manager JMX manager properties are configured as follows. Property jmx-manager jmx-manager-access-file Description Default If true then this member can become a JMX Manager. All other jmx-manager-* properties are used when it does become a JMX Manager. If this property is false then all other jmx-manager-* properties are ignored. By default the JMX Manager allows full access to all MBeans by any client. If this property is set to the name of a file, then it can restrict clients to only reading MBeans; they cannot modify MBeans. The access level can be configured differently in this file for each user name defined in the password file. For more information about the format of this file see Oracle's documentation of the false not set com.sun.management.jmxremote.access.file system property. Ignored if jmx-manager is false or if jmx-manager-port is zero. See Setting Up JMX Manager Authentication on page 305. jmx-manager-bind-address By default, the JMX Manager when configured with a port listens on all the not set local host's addresses. You can use this property to configure which particular IP address or host name the JMX Manager will listen on. This property is ignored if jmx-manager is false or jmx-manager-port is zero. jmx-manager-hostname-for-clients Hostname given to clients that ask the locator for the location of a JMX Manager. not set By default the IP address of the JMX Manager is used. However, for clients on a different network, you can configure a different hostname to be given to clients. Ignored if jmx-manager is false or if jmx-manager-port is zero. 304 jmx-manager-http-port Not used. If you require HTTP access for JMX management, use a standalone 8080 (not used) JMX Agent instead of a manager node. See Using a vFabric SQLFire JMX Agent on page 306. jmx-manager-password-file By default the JMX Manager allows clients without credentials to connect. If not set this property is set to the name of a file, only clients that connect with credentials that match an entry in this file will be allowed. Most JVMs require that the file vFabric SQLFire User's Guide Using Java Management Extensions (JMX) Property Description Default is only readable by the owner. For more information about the format of this file see Oracle's documentation of the com.sun.management.jmxremote.password.file system property. Ignored if jmx-manager is false or if jmx-manager-port is zero. See Setting Up JMX Manager Authentication on page 305. jmx-manager-port The port on which this JMX Manager listens for client connections. If this 1099 property is set to zero, SQLFire does not allow remote client connections. Alternatively, use the standard system properties supported by the JVM for configuring access from remote JMX clients. Ignored if jmx-manager is false. The Default RMI port is 1099. jmx-manager-ssl If true and jmx-manager-port is not zero, the JMX Manager accepts false only SSL connections. The ssl-enabled property does not apply to the JMX Manager, but the other SSL properties do. This allows SSL to be configured for just the JMX Manager without needing to configure it for the other SQLFire connections. Ignored if jmx-manager is false. jmx-manager-start If true, this member starts a JMX Manager when it boots. In most cases you false should not set this property to true because a JMX Manager is automatically started when needed on a member that sets jmx-manager to true. Ignored if jmx-manager is false. jmx-manager-update-rate The rate, in milliseconds, at which this member pushes updates to any JMX Managers. Currently this value should be greater than or equal to the statistic-sample-rate. 2000 Connecting to a JMX Manager After you start a member as a JMX Manager using the above options, you can access the manager with a JMX client by specifying a JMX URL with the connector path /jmxrmi. For example, when using the default RMI port the JMX URL is: service:jmx:rmi://bind-address/jndi/rmi://bind-address:1099/jmxrmi Note: If you configure a standalone JMX Agent instead of a JMX Manager, the connector path for the Agent is /jmxconnector. Stopping a JMX Manager To stop a JMX Manager, shut down the locator or server that hosts the JMX Manager. Or, use the JMX management API stopManager() method to stop a member from being a JMX Manager. When a Manager stops, it removes all federated MBeans from other members from its Platform MBeanServer. It also emits a notification to inform other members that it is no longer considered a JMX Manager. Setting Up JMX Manager Authentication To force JMX clients to authenticate into the SQLFire management system, you must configure authentication for the JMX Manager node. By default, the JMX manager allows clients without credentials to connect. To set up JMX authentication for the management system: 1. Verify that the have the jmx-manager SQLFire property is set to true on any node that you want to be able to become a JMX Manager and authenticate clients. If this property is set to false or not specified, then all other jmx-manager-* properties are ignored. 305 Managing and Monitoring vFabric SQLFire 2. Create a password file that contains entries for the user names and passwords you want to grant access to the SQLFire management and monitoring system. For example: #the sqlfiremonitor user has password Abc!@# #the sqlfiremanager user has password 123Gh2! sqlfiremonitor Abc!@# sqlfiremanager 123Gh2! 3. On each of your JMX Manager-enabled nodes, set the property jmx-manager-password-file to the name of the file you created in step 2. This will require clients to authenticate when connecting to a JMX Manager node in SQLFire. 4. If you wish to further restrict access to system operations, you can also set up an access file for the JMX Manager. The access file indicates whether the users listed in the password file have the ability to read system MBeans (monitor the system) or whether they can additionally modify MBeans (perform operations). For example, you can define the following: #the sqlfiremonitor user has readonly access #the sqlfiremanager user has readwrite access sqlfiremonitor readonly sqlfiremanager readwrite 5. On each of your JMX Manager-enabled nodes, set the SQLFire property jmx-manager-access-file to the name of the file you created in step 4. This will associate MBean permissions to the users who authenticate to the JMX Manager node in SQLFire. 6. If desired, enable SSL for your JMX Manager connections. To enable SSL, make sure the jmx-manager-port property is set to a non-zero value and set the jmx-manager-ssl property to true. Then configure all other SSL-related SQLFire properties as described in Configuring SSL Communication between the JMX Agent and Clients on page 313. Note: The SQLFire property ssl-enabled does not apply to the JMX Manager. Use the jmx-manager-ssl property instead. For more information about the format of the password and access file, see http://docs.oracle.com/javase/6/docs/technotes/guides/management/agent.html. Using a vFabric SQLFire JMX Agent The standalone SQLFire JMX Agent provides administrative and operational monitoring along with additional functionality such as health monitoring. You can use the JMX Agent to perform the following management tasks. • View the distributed system and its settings. • View distributed system members. • View and modify configuration attributes. • View runtime system and application statistics. • View query and application statistics. • Monitor the health of a vFabric SQLFire system and its components. The JMX Agent runs as a separate distributed system member, and can manage only a single distributed system. The JMX Agent uses connectors that are specified by JMX Remote v1.0. For information about JMX, see http://www.oracle.com/technetwork/java/javase/tech/javamanagement-140525.html. 306 vFabric SQLFire User's Guide Using Java Management Extensions (JMX) Note: If you require only RMI conenctor access for JMX clients, then it is simpler to use the built-in SQLFire JMX manager process. Use the standalone standalone Agent if you need to provide HTTP access for JMX clients using MX4J. Example Configuration This figure shows a sample configuration in which the JMX agent connects applications to a vFabric SQLFire distributed system. The architecture includes the following components. • Client applications that connect to the JMX Agent via HTTP or RMI. • A set of connectors and adapters that allow clients to contact and interact with the MBeans in the JMX Agent’s MBean server. See Configuring JMX Connectors and Adapters on page 311. • A set of SQLFire JMX MBeans that are used to manage the admin distributed system. See vFabric SQLFire MBeans on page 315. Starting the JMX Agent To start the SQLFire JMX Agent, use the sqlf agent command to invoke the Agent script. The general syntax for using sqlf agent to start an Agent is: sqlf agent start [-Jvmarg]* [-dir=dir] [prop=value]* 307 Managing and Monitoring vFabric SQLFire -Jvmarg A JVM option passed to the Agent’s JVM. For example, to define a 1 GB heap, you include this option: -J-Xmx1024M. To set a system property foo.bar to "true", you add -J-Dfoo.bar=true. -dir=dir The directory in which the Agent’s log file is written. The default is the current directory. For details, see Agent Log File on page 308. prop=value A configuration property and value passed to the Agent. You can define configuration properties on the command line or in the Agent properties file. For details, see Agent Properties File on page 308. This command line instantiates a JMX Agent with a non-default working directory and property file: sqlf agent start -dir=/usr/local/sqlfire property-file=/usr/local/sqlfire/agent/myprops.props When you launch the JMX Agent, you identify the distributed system to which you want to connect by specifying the lookup method (used to discover and communicate with other members of the distributed system) as either IP multicast or a SQLFire locator member. See Configuring Discovery Mechanisms on page 229. You specify these attributes as a list of prop=value pairs on the agent command line, or in the agent property file. For example, to connect to a SQLFire system that uses a locator: mcast-port=0 locators=host1[12345] To connect to a system that uses multicast: mcast-address=239.192.81.1 mcast-port=10021 The agent registers an AdminDistributedSystem MBean with the SQLFire distributed system. See Distributed System Properties for JMX Agent on page 309 for a list of additional properties. Additional properties are available to configure the supported JMX connectors/adaptors (RMIConnectorServer and HTTPAdaptor). For details, see the tables under Configuring JMX Connectors and Adapters on page 311. Agent Properties File and Log Files By default, the JMX Agent properties file is named agent.properties. You can specify a different properties file on the command line when you launch the JMX Agent. See Starting the JMX Agent on page 307 for more information. Agent Properties File The Agent looks for the properties file in the following locations and sequence: 1. 2. 3. 4. A directory that you explicitly specify with the -dir argument when starting the Agent The current directory Your home directory (the default) The CLASSPATH You can modify the values in the properties file via the HttpAdaptor or any supported JMX interface. Agent Log File By default, the Agent log file is named agent.log. You can specify a different log file as a command-line argument when you launch the JMX Agent. Basic JMX Agent Properties Specify values for these properties to configure the basic operation of the SQLFire JMX Agent. 308 vFabric SQLFire User's Guide Using Java Management Extensions (JMX) Argument Comments Default Value property-file Name of the properties file to load when starting the JMX Agent. See Agent Properties File on page 308. log-level Minimum level of log messages to be written. log-disk-space-limit Maximum disk space to allocate for logging, 0 in megabytes in the range 0..1000000. log-file-size-limit Maximum size of the JMX Agent log file, in 0 megabytes in the range 0..1000000. auto-connect If true, the JMX Agent automatically connects to the distributed system specified by the arguments mcast-port, mcast-address, locators, and remote-command. You specify these arguments on the command line or in the Agent properties file. See Distributed System Properties for JMX Agent on page 309. true refresh-interval Interval in seconds after which the system statistics are refreshed. 5 seconds config Related Topics Configuring JMX Connectors and Adapters on page 311 Configuring SSL Communication between the JMX Agent and Clients on page 313 Distributed System Properties for JMX Agent Specify values for these admin distributed system-specific properties as a list of prop=value pairs on the agent command line or in the JMX Agent’s properties file. The SSL properties listed here affect communication between members of the distributed system. Argument mcast-address Comments Default Value Multicast address of this distributed system. 239.192.81.1 To use IP multicast, you must also define mcast-port, the IP port. mcast-port Multicast port, a value in the range 0..65535. 10334 To use IP multicast, you must also define mcast-address, the IP address. membership-port-range Range of ports available for unicast UDP 1024-65535 messaging and for TCP failure detection. This range is specified as two integers separated by a minus sign. Different members can use different ranges. SQLFire randomly chooses two unique integers from this range for the member, one for UDP unicast messaging and the other for TCP failure detection messaging. Additionally, the system uniquely identifies the member using the combined host IP address and UDP port number. You may want to restrict the range of ports that SQLFire uses so the product can run in an environment where routers allow traffic only on certain ports. 309 Managing and Monitoring vFabric SQLFire Argument locators remote-command Comments Default Value Comma-delimited list whose elements have "" the form host[port]. When you use the SQLFire locator service, each locator is uniquely identified by the host on which it is running and the port on which it is listening. Default remote command prefix to use for command invocation on remote machines. rsh -n {HOST} {CMD} security-userPassword The password part of the credentials used to none authenticate the JMX Agent to the SQLFire distributed system. security-username The username part of the credentials used to none authenticate the JMX Agent to the SQLFire distributed system. ssl-enabled ssl-protocols ssl-ciphers ssl-require-authentication tcp-port Indicates whether to use the Secure Sockets Layer (SSL) protocol for communication between members of this distributed system. Valid values are true and false. A true setting requires the use of locators. false Space-separated list of valid SSL protocols any for this connection. Specify any protocol that is enabled by default in the configured Java Secure Sockets Extension (JSSE) provider. Space-separated list of valid SSL ciphers for any this connection. Specify any ciphers that are enabled by default in the configured JSSE provider. Indicates whether to require authentication for communication between members of the admin distributed system. Valid values are true and false. true TCP port to listen on for distributed system 0 communications. If set to zero, the operating system selects an available port. Each process on a machine must have its own TCP port. Some operating systems restrict the range of ports usable by non-privileged users, and using restricted port numbers can cause runtime errors in SQLFire startup. Valid values are in the range 0..65535. E-mail Notification Properties for the JMX Agent You can configure the Agent to provide e-mail notification for alerts and membership change events. Specify the notification properties in the Agent’s properties file or as a list of prop=value pairs on the agent command line. The properties file is the recommended method. 310 Argument Comments Default Value email-notification-enabled Whether to send e-mail notifications. false email-notification-from Originating address to put into the e-mail notifications. email-notification-host Host where the mail server is running - used to send the notifications. This must be set for vFabric SQLFire User's Guide Using Java Management Extensions (JMX) Argument Comments Default Value mails to be sent. The server’s default port is used for the notifications. email-notification-to Comma-separated list of e-mail addresses to which to send the notifications. This must be set for mails to be sent. This example defines properties for a e-mail notification in the Agent’s properties file: email-notification-enabled=true email-notification-from='[email protected]' email-notification-host='thinman' email-notification-to='[email protected],[email protected],[email protected]' The system sends the following types of notifications. Notification Type E-mail Subject Line System Alert—System alert that is raised in the members and can be set by a user. [Gemfire Alert] Distributed System: Member Crash—Alert of a member crash. [Gemfire Alert] Distributed System: Stat Alert—Created via GFMon, this notification evaluates a threshold for a functional value of one or more statistics. [Gemfire Alert] Distributed System: Membership change—Notification of a member joining, leaving, or being forcibly disconnected. [GemFire Notification]Distributed System: [GemFire Notification]Distributed System: Connecting to a JMX Agent After you start a JMX Agent, you can access the agent from a JMX client by specifying a JMX URL with the connector path /jmxconnector. For example, when using the default RMI port the JMX URL is: service:jmx:rmi://address/jndi/rmi://address:1099/jmxconnector Note: If you configure a locator or server as a JMX manager instead of starting a standalone JMX Agent, the connector path for the JMX Manager is /jmxrmi. Stopping the JMX Agent To stop the SQLFire JMX Agent, issue sqlf agent stop command. The basic syntax of the command is: sqlf agent stop [-dir=dir] where dir is the directory in which the Agent is running. Configuring JMX Connectors and Adapters The JMX Agent provides two interfaces for JMX clients based on RMIConnectorServer and MX4J HttpAdaptor. RMIConnectorServer Properties The SQLFire JMX Agent includes an RMIConnectorServer for clients to view and interact with the MBeans in the MBean server. See JSR 160 JMX Remote. 311 Managing and Monitoring vFabric SQLFire Under JRE 1.5, RMIConnectorServer is provided by JRE 1.5. See http://download.oracle.com/javase/1.5.0/docs/guide/jmx/tutorial/connectors.html for more information. The following properties configure the SQLFire Agent RMIConnectorServer. You can specify the properties either in the Agent properties file or as a list of prop=value pairs on the agent command line. Argument Comments Default Value rmi-bind-address IP address that the JMX Agent uses to communicate with the admin distributed system. "" This is required on: • Multi-homed hosts (machines with multiple network cards) • Windows systems when using IPv6 The rmi-bind-address argument must be specified on the agent start command line if jconsole or jmanage are running on a different host. If set to null - "" - all network addresses are used. rmi-enabled To enable the RMIConnectorServer, this must be true. true rmi-port RMI registry port, a value in the range 0..65535. 1099 rmi-registry-enabled If true, create an MX4J Naming MBean to serve as the RMI registry, and register the RMIConnector under the JNDI path /jmxconnector. More information is also available in the true com.gemstone.gemfire.admin.jmx.Agent Javadocs. rmi-server-port Port to use for the RMIConnectorServer. If set to 0 (zero) the server socket uses a dynamically allocated port. You might want to specify the port to use when the JMX agent is behind the firewall, for example. Valid values are in the range 0..65535. 0 Example Using the default settings, the SQLFire JMX Agent creates an RMI connector listening on available addresses at port 1099. JMX clients can connect to the process by specifying the JMX URL: service:jmx:rmi://address/jndi/rmi://address:1099/jmxconnector For example, to access the SQLFire Agent using jconsole from the same machine on which the agent is running, you would specify localhost as the address: jconsole service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jmxconnector Related Topics Starting the JMX Agent on page 307 312 vFabric SQLFire User's Guide Using Java Management Extensions (JMX) MX4J/Http Adaptor Properties The SQLFire JMX agent provides an HTML interface that is based on the MX4J HttpAdaptor. The HttpAdaptor provides a functional and easy-to-use interface with no development required, and is particularly useful to developers who want to explore and browse SQLFire JMX MBeans. For more details about this interface, consult the online documentation on the MX4J website: • http://mx4j.sourceforge.net/docs/index.html — MX4J Guide • http://mx4j.sourceforge.net/docs/ch05.html — MX4J HttpAdaptor documentation Access the HttpAdapter through your browser using the URL http://HttpAdaptor_host:port. The default port is 8080. The following properties configure the SQLFire Agent HttpAdaptor. You can specify the properties either in the Agent properties file or as a list of prop=value pairs on the agent command line. Argument Comments Default Value http-enabled To enable the HTTPAdaptor, this must be true. true http-bind-address Machine name or IP address to which the HTTP listening socket should be bound. If this value is "localhost", then the socket is bound to the loopback address (127.0.0.1) and the adapter is only accessible via the URL http://localhost:8080. If null, all network addresses are used. null http-port Value must be in the range 0..65535. 8080 http-authentication-enabled If true, require a password. false http-authentication-user User name. admin http-authentication-password User password. password Example Using the default settings, the SQLFire JMX Agent starts the MX4J/Http Adaptor on all available addresses at port 8080. You can access the SQLFire MBeans in a Web browser by specifying the URL http://address:8080. Related Topics Starting the JMX Agent on page 307 Configuring SSL Communication between the JMX Agent and Clients You can configure the JMX Agent to use the Secure Sockets Layer (SSL) protocol for securing connections from outside of the vFabric SQLFire distributed system. To do so, you begin by specifying these properties in the Agent’s properties file before you start the agent. SSL Communication Properties Argument Comment Default Value agent-ssl-enabled Indicates whether the JMX Agent uses the Secure Sockets Layer (SSL) protocol for false 313 Managing and Monitoring vFabric SQLFire Argument Comment Default Value communication outside of the SQLFire distributed system. agent-ssl-protocols Space-separated list of the valid SSL protocols for this connection. You can specify any protocol that is enabled by default in the configured Java Secure Sockets Extension (JSSE) provider. any agent-ssl-ciphers Space-separated list of the valid SSL ciphers for this connection. You can specify any ciphers that are enabled by default in the configured JSSE provider. any agent-ssl-require-authentication If true, require client authentication for RMI and other non-HTTP connectors/adaptors. true http-ssl-require-authentication If true, require client authentication for HTTP adaptors. false In addition to configuring these properties, you must generate a keystore with the JMX Agent's certificate, and export the Agent's certificate into all client keystores that will need to access the Agent for monitoring. The example that follows how to generate and use these keystores using the Java keytool utility. Note: You can also configure a SQLFire system to use SSL protocol for communication between system members. See Configuring Authentication and Authorization on page 249 for details. Example of Configuring SSL for JMX Agents Follow these steps to configure and start the JMX Agent with SSL enabled: 1. Configure the agent properties listed described in the preceding table. 2. Generate a keystore for the JMX Agent. This example store uses the alias "jmxagent" and creates a new keystore named admin.keystore: $ keytool -genkey -alias jmxagent -dname "CN=trusted" -validity 3650 -keypass password -keystore admin.keystore -storepass password -storetype JKS 3. Verify the new keystore file: $ keytool -list -keystore admin.keystore Enter keystore password: password Keystore type: JKS Keystore provider: SUN Your keystore contains 1 entry jmxagent, Mar 15, 2013, PrivateKeyEntry, Certificate fingerprint (MD5): 83:71:0D:E4:53:AF:5C:31:E4:43:3D:01:C7:2C:BC:05 314 vFabric SQLFire User's Guide Using Java Management Extensions (JMX) 4. Export a certificate that can be used by clients of the JMX Agent: $ keytool -export -alias jmxagent -keystore admin.keystore -file jmxagent_cert.crt Enter keystore password: password Certificate stored in file 5. Import the certificate into a new trust store that will be used by a JMX client: $ keytool -import -file jmxagent_cert.crt -alias jmxagent -keystore clientTrustStore -storepass password 6. Using a text editor, create an agent.properties file in the JMX Agent directory with the following property definitions: agent-ssl-enabled=true agent-ssl-require-authentication=false Note: Also include any additional properties required to start the JMX Agent and connection to your SQLFire distributed system (for example, define mcast-port and locators). This example accesses the JMX Agent using RMI; if you also want to access the Agent using HTTPS, include the property definition http-ssl-require-authentication=true. 7. Using a text editor, create an security.properties file in the JMX Agent directory with the following property definitions: javax.net.ssl.keyStoreType=jks javax.net.ssl.keyStore=/path/admin.keystore javax.net.ssl.keyStorePassword=password javax.net.ssl.trustStore=/path/admin.keystore javax.net.ssl.trustStorePassword=password security-username=username security-userPassword=password Be sure to replace the indicated paths and passwords with the actual values for your system. Note that security-username and security-password provide credentials to authenticate the JMX Agent to the SQLFire distributed system that it monitors. See Configuring User Authentication on page 249 for information about configuring authentication for SQLFire members. 8. Start the JMX Agent using the command: sqlf agent start -dir=agent-directory-path -J-DgemfireSecurityPropertyFile=path-to-security-properties 9. When starting the JMX client that will acess the JMX Agent, specify the -J-Djavax.net.ssl.trustStore and -J-Djavax.net.ssl.trustStorePassword options to point access the client trust store. For example, to start jconsole: $ jconsole -J-DgemfireSecurityPropertyFile=./clientTrustStore -J-Djavax.net.ssl.trustStorePassword=password 10. In jconsole, access the JMX Agent over SSL by specifying the remote process service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jmxconnector. (Specify the correct address or RMI port number if you started the Agent using non-default values.) vFabric SQLFire MBeans SQLFire uses MBeans associated with the vFabric Gemfire component to monitor the distributed system and its contents. The JMX MBeans are ModelMBeans that manage instances of the Admin API objects housed in the JMX Agent’s MBeanServer. The JMX Agent hosts an MBeanServer, instances of all MBeans registered for managing a distributed system, and server connectors for various types of clients. 315 Managing and Monitoring vFabric SQLFire This table shows the Gemfire JMX MBeans that are of interest when monitoring a SQLFire system, highlighting each MBean’s key attributes and operations. ObjectName(s) Description GemFire:type=Agent Represents the configuration of a SQLFire JMX Agent member. Agent attributes include the name of the Agent properties and log files (propertyFile and logFile attributes), limits for log file size and disk usage, locators, bind address information, and SSL information. For details, see Basic JMX Agent Properties on page 308 and Distributed System Properties for JMX Agent on page 309. Agent operations include adding and removing SSL vendor properties, managing the log file, saving configuration settings to the properties file, and connecting to the distributed system. After the GemFireAgent MBean connects to a distributed system, you can still invoke the operation connectToSystem to return the ObjectName for the AdminDistributedSystem MBean. GemFire:type=AdminDistributedSystem Represents the SQLFire distributed system, which is defined by three attributes: mcastAddress, mcastPort, and locators. AdminDistributedSystem operations include starting and stopping locators, creating DistributionLocator MBeans, managing locators and applications, monitoring SQLFire health, and displaying merged logs, licensing information, and system alerts. The AdminDistributedSystem MBean provides several predefined JMX Notifications that you can use to monitor your distributed system. In addition to these Notifications, you can use the JMX Monitor Service to monitor any attribute of any MBean. GemFire:type=DistributionLocator Represents a locator within a distributed system. Each locator is identified by its host, port, and bind address attributes. DistributionLocator operations include starting, stopping, and removing locators, as well as retrieving locator log files. GemFire.CacheVM:type=CacheVM Represents a SQLFire server or locator in the SQLFire distributed system. GemFire.Member:type=Application Represents a peer client in the SQLFire distributed system. GemFire.Statistic:type=CachPerfStats,name=RegionStats-schema Provides statistics for query and DML operations on SQLFire tables. GemFire.Statistic:type=CachPerfStats,name=RegionStats-partition-schema GemFire.Statistic:type=ConnectionStats,name=EmbeddedConnectionStats Provides statistics about embedded connections in the distributed system. GemFire.Statistic:type=DiskDirStatistics,name=disk_store Shows the number of bytes currently used by the disk store, as well as the maximum size of the disk store and other configuration attributes. GemFire.Statistic:type=DiskRegionStatistics Shows the per-table breakdown of disk store statistics. GemFire.Statistic:type=DiskStoreStatistics,name=disk_store Shows the number of compactions, reads and read bytes (for tables configured with eviction), writes, recovery stastics, and queue sizes for a disk store. GemFire.Statistic:type=DistributionStats,name=distributionStats Shows the current number of nodes in the distributed system (nodes attribute). The receivedBytes and sentBytes attributes provide a measure of network traffic to the distributed system. GemFire.Statistic:type=ResourceManagerStats,name=ResourceManagerStats Use these statistics when tables are configured for eviction. Attributes such as evictionStartEvents and evictionStopEvents indicate the number of times eviction actions are performed (evictionThreshold also shows the configured threshold for eviction). Attributes such as heapCriticalEvents, and heapSafeEvents show how heap size contributed to table eviction events. 316 vFabric SQLFire User's Guide Using Java Management Extensions (JMX) ObjectName(s) GemFire.Statistics:type=StatementStats Description Provides statistics about statement execution. This is created by invoking the manageStats operation of the GemFire.CacheVM or GemFire.Member MBeans, if statement statistics capture is enabled. See Evaluating Query Plans and Query Statistics on page 279. GemFire.Statistic:type=VMGCStats,name=ConcurrentMarkSweep Use the collections and collectionTime attributes to measure JVM garbage collection performance. If you monitor these attributes, also GemFire.Statistic:type=VMGCStats,name=ParNew enable GC logging at the JVM level to record additional information. GemFire.Statistic:type=VMMemoryPoolStats,name=CMS Old Gen-Heap memory Monitor the currentUsedMemory and currentMaxMemory attributes to measure the memory used in these pools. GemFire.Statistic:type=VMMemoryPoolStats,name=Par Eden Space-Heap memory GemFire.Statistic:type=VMMemoryPoolStats,name=Par Survivor Space-Heap memory GemFire.Statistic:type=VMMemoryUsageStats,name=vmHeapMemoryStats Monitor the usedMemory and maxMemory attributes to measure the memory used in this area. 317 Chapter 49 Best Practices for Tuning Performance You can help ensure optimum performance by following best practices for SQLFire servers and applications. Tune Application Logic Follow these guidelines for tuning applications. • Use prepared statements for all operations. This greatly reduces latency. • Avoid expensive join queries by denormalizing and adding constraints. • Design queries so that results are pruned to the smallest result set first. • Create indexes before loading data. • Use sufficient indexes to optimize frequently executed queries. Because indexes add to the footprint of your application, make sure that the indexes you add provide a meaningful performance benefit. • Minimize the use of transactions. SQLFire provides atomicity and isolation for single rows even without transactions. • Keep the transaction duration and the number of rows involved in the transaction as low as possible. SQLFire acquires locks eagerly, and long-lasting transactions increase the probability of conflicts and transaction failures. • Minimize the use of REPEATABLE_READ transactions. Reduce Distribution Overhead Latency-sensitive applications must minimize interprocess communication. For SQLFire, this means reducing traffic between clients and servers, and between servers, because the data itself is distributed. • Choose a partitioning strategy that colocates most data access and transactions in a single partition. • To assist with colocation, replicate smaller tables that are rarely modified • Avoid global indexes. • Avoid distributed transactions. • Use data-aware procedures to execute application logic locally to the data. • Use peer clients when possible. Peer clients have access to metadata about partitioned tables, and they can directly access the SQLFire server that has the needed data. By default, a thin client may be connected to a server that does not have the necessary data. If the server does not host the data, it must forward the client request to a server that does have it. This process adds a round-trip that is not necessary with peer clients. Peer clients also offload work from the servers, which allows servers to support more clients, including thin clients. However, peer clients are only appropriate in relatively small numbers. Embedded Peer-to-Peer Deployment on page 220 provides more details. • When using thin clients, set single-hop-enabled to true to minimize network round trips where possible. If necessary, increase the sqlfire.client.single-hop-max-connections system property to a value that gives the best performance for concurrent single-hop connections. Be sure to start a network server on each data store. See Enabling Single-Hop Data Access on page 124 for details on when single hop can be utilized. 319 Managing and Monitoring vFabric SQLFire Reduce Overhead of Eviction to Disk Reduce the memory overhead of tables, as well as the performance overhead. Reduce the memory overhead of tables. Some applications may benefit from evicting rows to disk in order to reduce heap space. However, enabling eviction also increases the per-row overhead that SQLFire requires to perform LRU eviction for the table. As a general rule, table eviction is only helpful for conserving memory if the non-primary key columns in a table are large: 100 bytes or more. Reduce the performance overhead of eviction to disk: • Scale the number of data stores and/or increase the heap size to keep more rows in memory. • Do not configure eviction on small, frequently-used tables. • Only configure eviction on large tables that contain data that is used infrequently. • Use the DESTROY action rather than overflowing to disk to clean out data that is no longer needed. • Tune disk I/IO. See Tuning Disk I/O on page 321. See How LRU Eviction Works on page 197. Minimize Update Latency for Replicated Tables Keep in mind that when an application updates a replicated table, SQLFire performs the update on each member that hosts a replica of the table. The update latency for replicated tables increases with the number of SQLFire members that host the table. SQLFire clients experience the update latency at different times. Peer clients incur the latency cost at execution time, while thin clients incur the latency cost only at commit time. When possible, update highly-replicated tables outside of larger transactions. Tune FabricServers These JVM-related recommendations pertain to the 64-bit version 1.6 JVM running on Linux. • Use JDK 1.6.0_26 or higher. This provides significantly better performance than earlier versions for some SQLFire applications. • Use –server for JVMs that will start servers with the FabricServer API. • Set initial and maximum heap to the same value. This allocates a contiguous memory segment. When using the sqlf script to start the server, set –initial-heap equal to –max-heap. Using –initial-heap equal to –max-heap also enables the SQLFire default JVM resource management settings. When using the FabricServer API, set –Xms equal to –Xmx and specify all other JVM options required for JVM resource management. • Set –XX:+UseConcMarkSweepGC to use the concurrent low-pause garbage collector and the parallel young generation collector. The low-pause collector sacrifices some throughput in order to minimize stop-the-world GC pauses for tenured collections. It does require more headroom in the heap, so increase the heap size to compensate. The sqlf script starts fabric servers with this collector by default. • Set -XX:+DisableExplicitGC to disable full garbage collection. This causes calls to System.gc() to be ignored, avoiding the associated long latencies. • Set –XX:CMSInitiatingOccupancyFraction=50 or even lower for high throughput latency-sensitive applications that generate large amounts of garbage in the tenured generation, such as those that have high rates of updates, deletes, or evictions. This setting tells the concurrent collector to start a collection when tenured occupancy is at the given percentage. With the default setting, a high rate of tenured garbage creation can outpace the collector and result in OutOfMemoryError. Too low of a setting can affect throughput by doing unnecessary collections, so test to determine the best setting. The sqlf script sets this for fabric servers by default. 320 vFabric SQLFire User's Guide Best Practices for Tuning Performance • If short-lived objects are being promoted to the tenured generation, set –XX:NewSize=, where n is large enough to prevent this from occurring. Increasing this value tends to increase throughput but also latency, so test to find the optimum value, usually somewhere between 64m and 1024m. • Tune heap settings so that occupancy stays below 70%. This helps reduce latency. • The parallel compactor in JDK 6 is not available with the concurrent low-pause collector. Churn in the tenured generation causes fragmentation that can eventually cause stop-the-world compactions. You can postpone the issue by using the largest heap that fits into memory, after allowing for the operating system. • If heap space is an issue, –XX:+UseCompressedOops is turned on by default if you are running with 64-bit JDK 1.6.0_24 or higher. This can reduce heap usage by up to 40% by reducing managed pointers for certain objects to 32-bit. However, this can lower throughput and increase latency. It also limits the application to about four billion objects. • Set conserve-sockets=false in the boot properties. This causes each server to use a dedicated threads to send to and receive from each of its peers. This uses more system resources, but can improve performance by removing socket contention between threads and allowing SQLFire to optimize certain operations. If your application has very large numbers of servers and/or peer clients, test to see which setting gives the best results. Peer clients that are read-heavy with very high throughput can benefit from conserving sockets while leaving conserve-sockets false in the data stores • Set enable-time-statistics=false in the boot properties and set enable-timestats=false in all connections (including client connections) to turn off time statistics. This eliminates a large number of calls to gettimeofday. • For applications that will always use a single server, you can make it a "loner" by setting the mcast-port=0 and configuring no locators. Knowing there will be no distribution allows SQLFire to do a few additional optimizations. Thin clients must then connect directly to the server. Also, peer clients cannot be used in this case. Tuning Disk I/O Most SQLFire applications that access the hard disk work well with synchronous disk stores and reasonably fast disks. If disk I/O becomes a bottleneck, you can configure the system to minimize seek time. The degree of tuning depends on your application’s data access patterns: • Place the disk store directories used by a SQLFire server on local drives or on a high-performance Storage Area Network (SAN). • If you have limited disk space, use smaller oplog sizes for disk stores to avoid expensive file deletes. A value of 512 MB for MAXLOGSIZE is a good starting point. • If space allows, turn off automatic oplog compaction in disk stores by setting AUTOCOMPACT to false. This prevents latency-sensitive writes to new oplogs from competing with seeks and writes related to compaction. Oplogs are still removed when they no longer contain current data. When compaction is unavoidable, set ALLOWFORCECOMPACTION to true and use sqlf to do manual compaction at a time when system activity is low or the system is offline. • Run backups with sqlf when system activity is low or the system is offline. • ASYNCHRONOUS disk stores can give some latency benefit for applications with infrequent writes that flush using a TIMEINTERVAL. They can also reduce disk I/O for applications that do very frequent writes to the same data, because these are conflated in the buffer. But asynchronous disk stores offer insignificant benefit in most cases and use heap space that can be better utilized elsewhere. Instead, use SYNCHRONOUS disk stores and let the operating system handle buffering. This simplifies application design and performs well with modern operating systems and disk storage. • Avoid configuring tables for expiration with overflow to disk, especially when expired data is frequently read. This increases disk seek times and latency, in addition to fragmenting the heap. • Use different disk stores for persistence and overflow, and map them to different physical disks. This practice isolates the fast sequential writes used in persistence from the higher latency random access caused by faulting data from disk into memory. 321 Managing and Monitoring vFabric SQLFire • A disk store that supports overflow or persistence with overflow can benefit from using multiple directories mapped to different disks. • Isolate disk I/O for your application from that of other applications, including the operating system. Running SQLFire in Virtualized Environments Using a newer operating system version such as Red Hat 6 or SLES 11 can help performance in virtual environments. VMware provides a best practices guide. See the Enterprise Java Applications on VMware Best Practices Guide for detailed information about deploying applications on VMware vSphere™. Use newer operating system versions, such as RedHat 6 and SLES 11, to avoid issues with the performance of gettimeofday in virtualized environments. SQLFire makes calls to gettimeofday for managing membership, distribution timeouts, expiration, eviction, recovery, and so forth, and a much larger number of calls when enable-time-statistics=true or enable-timestats=true. 322 vFabric SQLFire User's Guide Chapter 50 Detecting and Handling Network Segmentation ("Split Brain") When network segmentation occurs, a distributed system that does not handle the partition condition properly will allow multiple subgroups to form. This condition can lead to numerous problems, including distributed applications operating on inconsistent data. For example, because thin clients connecting to a server cluster are not tied into the membership system, a client might communicate with servers from multiple subgroups. Or, one set of clients might see one subgroup of servers while another set of clients cannot see that subgroup but can see another one. SQLFire handles this problem by allowing only one subgroup to form and survive. The distributed systems and caches of other subgroups are shut down as quickly as possible. Appropriate alerts are raised through the SQLFire logging system to alert administrators to take action. Network partition detection in SQLFire is based on the concept of a lead member and a group management coordinator. The coordinator is a member that manages entry and exit of other members of the distributed system. For network partition detection, the coordinator is always a SQLFire locator. The lead member is always the oldest member of the distributed system that does not have a locator running in the same process. Given this, two situations will cause SQLFire to declare a network partition: • If both a locator and the lead member leave the distributed system abnormally within a configurable period of time, a network partition is declared and the caches of members who are unable to see the locator and the lead member are immediately closed and disconnected. If a locator or lead member's distributed system are shut down normally, SQLFire automatically elects a new one and continues to operate. • If no locator can be contacted by a member, it declares a network partition has occurred, closes itself, and disconnects from the distributed system. You enable network partition detection by setting the enable-network-partition-detection distributed system property to true. Enable network partition detection in all locators and in any other process that you should be sensitive to network partitioning. Processes that do not have network partition detection enabled are not eligible to be the lead member, so their failure will not trigger declaration of a network partition. Note: The distributed system must contain locators to enable network partition detection. 323 Part 9 vFabric SQLFire Reference vFabric SQLFire Reference describes the SQLFire command-line utilities, APIs, and Standard Query Language (SQL) implementation. Topics: • • • • • • • • • • Configuration Properties JDBC API sqlf Launcher Commands sqlf Interactive Commands SQLFire API SQL Language Reference System Tables Exception Messages and SQL States ADO.NET Driver Reference vFabric SQLFire Limitations 325 Chapter 51 Configuration Properties SQLFire uses JDBC connection properties, connection boot properties, and Java system properties to configure SQLFire members and connections. • Property Types on page 327 • Property Prefixes on page 328 • Using Non-ASCII Strings in SQLFire Property Files on page 328 • List of Property Names on page 328 • Configuration Property Reference on page 331 Property Types SQLFire configuration properties are divided into the following property types: • Connection properties. Connection properties configure the features of a SQLFire member or a SQLFire client connection when you start or connect to a SQLFire member. You can define connection properties directly in the JDBC connection URL (or in the "connect" command in an interactive sqlf session). You can also define connection properties in the sqlfire.properties file or as Java system properties. For example, use -J-Dproperty_name=property_value when you execute a sqlf utility. Or, use the JAVA_ARGS environment variable to define a Java system property for an interactive sqlf session (JAVA_ARGS="-Dproperty_name=property_value"). Note: You must add a prefix to certain connection property names in order to specify those properties in sqlfire.properties or as Java system properties. See Property Prefixes on page 328. Connection properties can be further categorized as either boot properties or client properties: • Boot properties. A boot connection property configures features of a SQLFire member, and can only be applied with the first connection that starts a SQLFire member. You can specify boot properties when you start a SQLFire member using the FabricServer API or sqlf command, when you make the first connection to an embedded SQLFire member with the JDBC embedded driver, or when you use the connect peer command from an interactive sqlf session to start a peer client. Boot properties have no effect when they are specified on connections to a member after the member has started. Boot properties have no effect when they are specified on a thin client connection. • For example, the server-groups property configures a data store's server groups when the data store boots. If you specify server-groups on any subsequent connection to the data store, the server group configuration is not changed. • Client properties. A client connection property configures features of the client connection itself, and can be used with the JDBC thin client drive (for example, using a JDBC thin client connection URL or the connect client command from an interactive sqlf session). • System properties. Certain SQLFire configuration properties must be specified either in the sqlfire.properties file or as Java system properties (using -J-Dproperty_name=property_value with a sqlf utility, or setting 327 vFabric SQLFire Reference JAVA_ARGS="-Dproperty_name=property_value" for an interactive sqlf session). You cannot define these properties in a JDBC URL connection. Many of these SQLFire system properties affect features of the SQLFire member at boot time. The names of SQLFire system properties always include the "sqlfire." prefix. For example, all properties that configure LDAP server information for user authentication must be specified as Java system properties, rather than JDBC properties, when you boot a server. Certain properties have additional behaviors or restrictions. See the individual property descriptions for more information. Property Prefixes You must add a prefix to certain connection and boot property names when you define those properties in the sqlfire.properties file or as Java system properties. The Prefix row in each property table lists a prefix value when one is required. Where indicated, the "sqlfire." prefix is required when defining the property either in sqlfire.properties or as a Java system property. The "gemfire." prefix is required only when defining a Java system property. Do not use an indicated prefix when you specify the property in a connection string or with the FabricServer API. If no prefix is specified, use only the indicated property name in all circumstances. For example, use "host-data" whether you define this property in sqlfire.properties, as a Java system property, or as a property definition for FabricServer. Using Non-ASCII Strings in SQLFire Property Files You can specify Unicode (non-ASCII) characters in vFabric SQLFire property files by using a \uXXXX escape sequence. For a supplementary character, you need two escape sequences, one for each of the two UTF-16 code units. The XXXX denotes the 4 hexadecimal digits for the value of the UTF-16 code unit. For example, a properties file might have the following entries: s1=hello there s2=\u3053\u3093\u306b\u3061\u306f For example, in sqlfire.properties, you might write: log-file=my\u00df.log to indicate the desired property definition of log-file=myß.log. If you have edited and saved the file in a non-ASCII encoding, you can convert it to ASCII with the native2ascii tool included in your Oracle Java distribution. For example, you might want to do this when editing a properties file in Shift_JIS, a popular Japanese encoding. For more information on internationalization in Java, see http://www.oracle.com/us/technologies/java/faq-jsp-138165.html. List of Property Names The following table lists all of the vFabric SQLFire configuration properties names and provides links to each property reference page. Connection Properties System Properties Boot Properties Client Properties ack-severe-alert-threshold auth-provider gemfire.DISKSPACE_WARNING_INTERVAL ack-wait-threshold default-recovery-delay gemfire.WRITE_LOCK_TIMEOUT 328 vFabric SQLFire User's Guide Configuration Properties Connection Properties System Properties Boot Properties Client Properties archive-disk-space-limit disable-streaming gemfire.READ_LOCK_TIMEOUT archive-file-size-limit drdaID gemfire.LOCK_MAX_TIMEOUT async-distribution-timeout enable-stats gemfire.preAllocateIF on page 338 async-max-queue-size enable-timestats gemfire.preAllocateIF on page 338 async-queue-timeout enable-tx-wait-mode gemfire.tx-disable-batching auth-provider load-balance bind-address log-file sqlfire.datadictionary.allow-startup-errors on page 354 config-scripts password conserve-sockets read-timeout departure-correlation-window secondary-locators disable-tcp single-hop-enabled distributed-system-id skip-listeners enable-network-partition-detection ssl enable-time-statistics sync-commits enforce-unique-host user host-data init-scripts jmx-manager jmx-manager-access-file jmx-manager-bind-address jmx-manager-hostname-for-clients jmx-manager-http-port jmx-manager-password-file jmx-manager-port jmx-manager-ssl jmx-manager-start jmx-manager-update-rate keepalive-count on page 342 keepalive-idle on page 342 keepalive-interval on page 342 license-serial-number sqlfire.drda.host sqlfire.drda.keepAlive sqlfire.drda.logConnections sqlfire.drda.maxThreads sqlfire.drda.minThreads sqlfire.drda.portNumber sqlfire.drda.securityMechanism sqlfire.drda.sslMode sqlfire.drda.streamOutBufferSize sqlfire.drda.timeSlice sqlfire.drda.trace sqlfire.drda.traceAll sqlfire.drda.traceDirectory sqlfire.auth-ldap-search-base sqlfire.auth-ldap-search-dn sqlfire.auth-ldap-search-filter sqlfire.auth-ldap-search-pw sqlfire.auth-ldap-server sqlfire.authz-default-connection-mode sqlfire.authz-full-access-users sqlfire.authz-read-only-access-users sqlfire.history sqlfire.client.single-hop-max-connections sqlfire.sql-authorization license-server-timeout license-working-dir locators log-disk-space-limit log-file 329 vFabric SQLFire Reference Connection Properties Boot Properties System Properties Client Properties log-file-size-limit log-level max-num-reconnect-tries max-wait-time-reconnect mcast-address mcast-flow-control mcast-port mcast-recv-buffer-size mcast-send-buffer-size mcast-ttl member-timeout membership-port-range password persist-dd redundancy-zone security-log-file security-log-level security-peer-verifymember-timeout server-auth-provider server-bind-address server-groups shutdown socket-buffer-size socket-lease-time sqlfire.language.permissionsCacheSize sqlfire.language.spsCacheSize sqlfire.language.statementCacheSize sqlfire.language.tableDescriptorCacheSize sqlfire.max-lock-wait sqlfire.properties sqlfire.query-cancellation-interval sqlfire.security. Properties (prefix) sqlfire.stream.error.logSeverityLevel sqlfire.storage.tempDirectory sqlfire.system.home ssl-ciphers 330 vFabric SQLFire User's Guide Configuration Properties Connection Properties System Properties Boot Properties Client Properties ssl-enabled ssl-protocols ssl-require-authentication start-locator statistic-archive-file statistic-sample-rate statistic-sampling-enabled sync-commits sys-disk-dir tcp-port udp-fragment-size udp-recv-buffer-size udp-send-buffer-size user writable-working-dir Configuration Property Reference ack-severe-alert-threshold Description The number of seconds the distributed system waits after the ack-wait-threshold for a message to be acknowledged before it issues an alert at severe level. A value of zero disables this feature. Default Value 0 (disabled) Property Type connection (boot) Prefix gemfire. ack-wait-threshold Description The number of seconds a distributed message waits for acknowledgment before it sends an alert to signal that something might be wrong with the system member that is unresponsive. After sending this alert the waiter continues to wait. The alerts are logged in the system member’s log as warnings. Valid values are in the range 0...2147483647 Default Value 15 Property Type connection (boot) Prefix gemfire. 331 vFabric SQLFire Reference archive-disk-space-limit Description The maximum size in megabytes of all inactive statistic archive files combined. If this limit is exceeded, inactive archive files are deleted, oldest first, until the total size is within the limit. If set to zero, disk space use is unlimited. Default Value 0 (unlimited) Property Type connection (boot) Prefix gemfire. archive-file-size-limit Description The maximum size in megabytes of a single statistic archive file. Once this limit is exceeded, a new statistic archive file is created, and the current archive file becomes inactive. If set to zero, file size is unlimited. Default Value 0 (unlimited) Property Type connection (boot) Prefix gemfire. async-distribution-timeout Description Note: This setting controls only peer-to-peer communication and does not apply to client/server or multi-site communication. Number of milliseconds a process that is publishing to this process should attempt to distribute a cache operation before switching over to asynchronous messaging for this process. The switch to asynchronous messaging lasts until this process catches up, departs, or some specified limit is reached, such as async-queue-timeout or async-max-queue-size. To enable asynchronous messaging, the value must be set above zero. Valid values are in the range 0..60000. Default Value 0 (disabled) Property Type connection (boot) Prefix gemfire. async-max-queue-size Description Note: This setting controls only peer-to-peer communication and does not apply to client/server or multi-site communication. It applies to non-conflated asynchronous queues for members that publish to this member. Maximum size of the queue in megabytes before the publisher asks this member to leave the distributed system. Valid values are in the range 0..1024. Default Value 8 Property Type connection (boot) 332 vFabric SQLFire User's Guide Configuration Properties Prefix gemfire. async-queue-timeout Description Note: This setting controls only peer-to-peer communication and does not apply to client/server or multi-site communication. It affects asynchronous queues for members that publish to this member. Maximum milliseconds the publisher waits with no distribution to this member before it asks the member to leave the distributed system. Used for handling slow receivers. Default Value 6000 Property Type connection (boot) Prefix gemfire. auth-provider Description Specifies the authentication scheme to use for network clients. The available SQLFire implementations are BUILTIN and LDAP. You can also specify the name of a custom provider class that implements the UserAuthenticator on page 478 interface. Default Value None Property Type connection (boot) Prefix sqlfire. bind-address Description Note: This setting is relevant only for multi-homed hosts (machines with multiple network interface cards). Adapter card the cache binds to for peer-to-peer communication. It also specifies the default location for SQLFire servers to listen on, which is used unless overridden by the server-bind-address. Specify the IP address, not the hostname, because each network card may not have a unique hostname. An empty string (the default) causes the member to listen on the default card for the machine. This attribute is a machine-wide attribute used for system member and client/server communication. It has no effect on locator location, unless the locator is embedded in a member process. Default Value not set Property Type connection (boot) Prefix gemfire. config-scripts Description Specifies one or more SQL script files to execute immediately, before loading DDL from the data dictionary. Use a comma-separated list of files to supply multiple values. Default Value not set Property Type connection (boot) 333 vFabric SQLFire Reference Prefix sqlfire. conserve-sockets Description Specifies whether sockets are shared by the system member’s threads. If true, threads share, and a minimum number of sockets are used to connect to the distributed system. If false, every application thread has its own sockets for distribution purposes. You can override this setting for individual threads inside your application. Where possible, it is better to set conserve-sockets to true and enable the use of specific extra sockets in the application code if needed. The length of time a thread can have exclusive access to a socket can be configured with socket-lease-time. Note: WAN deployments increase the messaging demands on a SQLFire system. To avoid hangs related to WAN messaging, always set conserve-sockets=false for SQLFire members that participate in a WAN deployment. See Prerequisites for WAN Replication on page 241. Default Value true Property Type connection (boot) Prefix gemfire. default-recovery-delay Description Specifies a default RECOVERYDELAY value for all tables in the cluster. If a SQLFire member leaves the cluster and no new members join, the remaining SQLFire members wait for a period of time before they perform recovery to satisfy the redundancy requirements of partitioned tables. This attribute specifies the period of time to wait before initiating recovery. Note: SQLFire always initiates recovery for redundant, partitioned tables when a new SQLFire member joins the cluster. A value of -1, the default value, indicates that no recovery is performed unless a new SQLFire member joins the cluster, or unless individual tables override the recovery delay by specifying the RECOVERYDELAY clause in their CREATE Default Value -1 Property Type connection Prefix sqlfire. TABLE statements. departure-correlation-window Description The number of seconds of process failure history kept by the system for correlating the loss of processes eligible to be the membership coordinator and the lead member. Default Value 1800 Property Type connection (boot) Prefix gemfire. 334 vFabric SQLFire User's Guide Configuration Properties disable-streaming Description Disables results streaming on the query node for this connection. Disabling streaming degrades performance and requires more memory for large query results, but provides more predictable results if a SQLFire member happens to go down while iterating over a ResultSet. When this property is not enabled, a SQLException with state SQLF_NODE_SHUTDOWN is thrown if a member goes offline in the middle of ResultSet iteration; in this case, the application has to retry the query. When this property is enabled, SQLFire waits for at least one result from each member and does not group results from members. This provides transparent failover if a member goes offline. Default Value false Property Type connection Prefix sqlfire. disable-tcp Description Boolean indicating whether to disable the use of TCP/IP sockets for inter-cache point-to-point messaging. If disabled, the cache uses datagram (UDP) sockets. Default Value false Property Type connection (boot) Prefix gemfire. distributed-system-id Description Identifier used to distinguish messages from different distributed systems. When starting a locator, set this property to a unique value for the cluster in a multi-site (WAN) configuration. Valid values are integers in the range -1...255. All locators for a single cluster must use the same value. -1 means no setting. Individual SQLFire members can use the setting of -1 and connect to one or more locators that specify a unique distribute-system-id. Default Value -1 Property Type connection (boot) Prefix gemfire. drdaID Description Sets the connection identity. Default Value Connection number Property Type connection Prefix n/a enable-network-partition-detection Description Boolean instructing the system to detect and handle splits in the distributed system, typically caused by a partitioning of the network (split brain) where the distributed system is running. 335 vFabric SQLFire Reference Default Value false Property Type connection (boot) Prefix gemfire. enable-stats Description This property can only be used with a peer client connection; you cannot use it from a thin client. Enables statistics collection at the statement level for the associated connection. See Evaluating System and Application Performance on page 291. Default Value false Property Type connection Prefix sqlfire. enable-time-statistics Description Boolean instructing the system to track time-based statistics for the distributed system. Disabled by default for performance. Default Value false Property Type connection (boot) Prefix gemfire. enable-timestats Description Note: This property can only be used with a peer client connection; you cannot use it from a thin client. Boolean instructing the system to track time-based statistics for the current connection. Disabled by default for performance. See Evaluating System and Application Performance on page 291. Default Value false Property Type connection Prefix sqlfire. enable-tx-wait-mode Description Uses lock waiting mode instead of the default "fail-fast" conflict mode for transactions. In lock waiting mode, a committed transaction is serialized and waits for other ongoing transactions instead of conflicting with those transactions. Default Value false Property Type connection Prefix sqlfire. 336 vFabric SQLFire User's Guide Configuration Properties enforce-unique-host Description Boolean that determines whether SQLFire puts redundant copies of the same data in different members running on the same physical machine. By default, SQLFire tries to put redundant copies on different machines, but it puts them on the same machine if no other machines are available. Setting this property to true prevents this and requires different machines for redundant copies. Default Value false Property Type connection (boot) Prefix gemfire. gemfire.DISKSPACE_WARNING_INTERVAL Description Configures the frequency (in milliseconds) with which SQLFire logs warning messages for low disk space conditions. SQLFire logs a low disk space warning in the following situations: • For a log file directory it logs a warning if the available space is less than 100 MB. • For a disk store directory it logs a warning if the usable space is less than 1.15 times the space required to create a new oplog file. • For the data dictionary directory it logs a warning if the remaining space is less than 50 MB. Default Value 10000 Property Type system Prefix n/a gemfire.WRITE_LOCK_TIMEOUT Description The time to wait before throwing a conflict exception (X0Z02) for a write-write conflict that is detected between two transactions. If the first transaction that acquired the lock on the conflicting row completes in this period of time (for example, it commits or aborts) then no conflict occurs. However, keep in mind that SQLFire does not have any built-in mechanism for detecting distributed deadlocks, so setting this property too high can cause two interlocked transactions to both block for that period of time. Keep this timeout value small, because increasing the value can have a negative impact on the overall throughput of a system that has transactions that perform lots of DML. The default value is 0, which means that the system throws a conflict immediately when it is detected. If you change this property, set it to the same value on every data store member in your distributed system. This property configures conflict detection for READ_COMMITTED and REPEATABLE_READ transactions. See Supported Transaction Isolation Levels on page 158. Default Value 0 Property Type system Prefix n/a gemfire.READ_LOCK_TIMEOUT Description The time to wait before throwing a conflict exception (X0Z02) for a write-read conflict that is detected between two REPEATABLE_READ transactions. If the read lock acquired by the transaction that has read the conflicting row completes in this period of time (for example, it commits or aborts) then no conflict occurs for the transaction that is writing the row. However, keep in mind that SQLFire does not have any built-in mechanism for detecting distributed deadlocks, so setting this property too high can cause two interlocked transactions to both block for that period of time. 337 vFabric SQLFire Reference Keep this value small. The default value is 0, which means that the system throws a conflict for the writer immediately on detection during commit. If you change this property, set it to the same value on every data store member in your distributed system. This property configures conflict detection for READ_COMMITTED and REPEATABLE_READ transactions. See Supported Transaction Isolation Levels on page 158. Default Value 0 Property Type system Prefix n/a gemfire.LOCK_MAX_TIMEOUT Description This is the maximum time to wait for a transaction that is committing a row that the current transaction is trying to read or write. Do not change this property unless transactions involve a large number of writes and potentially can take a very long time during commit to write to datastores. The default is 5 minutes. If you change this property, set it to the same value on every data store member in your distributed system. This property configures conflict detection for READ_COMMITTED and REPEATABLE_READ transactions. See Supported Transaction Isolation Levels on page 158. Default Value 5 Property Type system Prefix n/a gemfire.preAllocateDisk Description Boolean that determines whether SQLFire pre-allocates the disk space required for disk store files (.crf and .drf extensions) using operating system-native calls. Pre-allocating disk space can avoid later failures or hangs caused by disk full conditions. See also gemfire.preAllocateIF on page 338. Default Value false Property Type system Prefix n/a gemfire.preAllocateIF Description Boolean that determines whether SQLFire pre-allocates the disk space required for disk store metadata files (.if extensions) using operating system-native calls. Pre-allocating disk space can avoid later failures or hangs caused by disk full conditions. See also gemfire.preAllocateDisk on page 338. Default Value false Property Type system Prefix n/a 338 vFabric SQLFire User's Guide Configuration Properties gemfire.tx-disable-batching Description Boolean that determines whether SQLFire detects conflicts in thin client transactions lazily or at operation time. With the default value of "false," SQLFire detects any conflicts in DML operations lazily. DML conflicts may be thrown by the system at some point later in the transaction (for example, even when executing queries or at commit time). Set this option to "true" on all data store members in your distributed system to immediately detect conflicts at operation time for thin clients. Note: Enabling gemfire.tx-disable-batching can degrade performance significantly. Enable this option only after you have thoroughly tested the setting in your system, and you have determined that the performance tradeoff is necessary to provide immediate conflict detection with thin clients. Default Value false Property Type system Prefix n/a host-data Description Specifies whether this SQLFire member will host table data. Setting this value to false boots a SQLFire accessor member with the full SQLFire engine. The accessor (or peer client) participates in routing queries to other members, but it does not host replicated or partitioned data, and it does not persist the data dictionary. Setting this value to true boots a SQLFire data store. Data stores host data, and they persist the data dictionary by default. All data stores in the same SQLFire cluster must use the same persistence settings (using the persist-dd boot property). You should generally specify one or more server groups for the data store by including the server-groups attribute. By default, all new SQLFire data stores are added to the default server group. Default Value true Property Type connection (boot) Prefix sqlfire. init-scripts Description One or more SQL script files to execute after loading DDL from the data dictionary. Use a comma-separated list of files to supply multiple values. Default Value not set Property Type connection (boot) Prefix sqlfire. jmx-manager Description If true then this member can become a JMX Manager. All other jmx-manager-* properties are used when it does become a JMX Manager. If this property is false then all other jmx-manager-* properties are ignored. Default Value false 339 vFabric SQLFire Reference Property Type connection (boot) Prefix n/a jmx-manager-access-file Description By default the JMX Manager allows full access to all MBeans by any client. If this property is set to the name of a file, then it can restrict clients to only reading MBeans; they cannot modify MBeans. The access level can be configured differently in this file for each user name defined in the password file. For more information about the format of this file see Oracle's documentation of the com.sun.management.jmxremote.access.file system property. Ignored if jmx-manager is false or if jmx-manager-port is zero. See Setting Up JMX Manager Authentication on page 305. Default Value not set Property Type connection (boot) Prefix n/a jmx-manager-bind-address Description By default, the JMX Manager when configured with a port listens on all the local host's addresses. You can use this property to configure which particular IP address or host name the JMX Manager will listen on. This property is ignored if jmx-manager is false or jmx-manager-port is zero. Default Value not set Property Type connection (boot) Prefix n/a jmx-manager-hostname-for-clients Description Hostname given to clients that ask the locator for the location of a JMX Manager. By default the IP address of the JMX Manager is used. However, for clients on a different network, you can configure a different hostname to be given to clients. Ignored if jmx-manager is false or if jmx-manager-port is zero. Default Value not set Property Type connection (boot) Prefix n/a jmx-manager-http-port Description Not used. If you require HTTP access for JMX management, use a standalone JMX Agent instead of a manager node. See Using a vFabric SQLFire JMX Agent on page 306. Default Value 8080 (not used) Property Type connection (boot) Prefix n/a 340 vFabric SQLFire User's Guide Configuration Properties jmx-manager-password-file Description By default the JMX Manager allows clients without credentials to connect. If this property is set to the name of a file, only clients that connect with credentials that match an entry in this file will be allowed. Most JVMs require that the file is only readable by the owner. For more information about the format of this file see Oracle's documentation of the com.sun.management.jmxremote.password.file system property. Ignored if jmx-manager is false or if jmx-manager-port is zero. See Setting Up JMX Manager Authentication on page 305. Default Value not set Property Type connection (boot) Prefix n/a jmx-manager-port Description The port on which this JMX Manager listens for client connections. If this property is set to zero, SQLFire does not allow remote client connections. Alternatively, use the standard system properties supported by the JVM for configuring access from remote JMX clients. Ignored if jmx-manager is false. The Default RMI port is 1099. Default Value 1099 Property Type connection (boot) Prefix n/a jmx-manager-ssl Description If true and jmx-manager-port is not zero, the JMX Manager accepts only SSL connections. The ssl-enabled property does not apply to the JMX Manager, but the other SSL properties do. This allows SSL to be configured for just the JMX Manager without needing to configure it for the other SQLFire connections. Ignored if jmx-manager is false. Default Value false Property Type connection (boot) Prefix n/a jmx-manager-start Description If true, this member starts a JMX Manager when it boots. In most cases you should not set this property to true because a JMX Manager is automatically started when needed on a member that sets jmx-manager to true. Ignored if jmx-manager is false. Default Value false Property Type connection (boot) Prefix n/a jmx-manager-update-rate Description The rate, in milliseconds, at which this member pushes updates to any JMX Managers. Currently this value should be greater than or equal to the statistic-sample-rate. 341 vFabric SQLFire Reference Default Value 2000 Property Type connection (boot) Prefix n/a keepalive-count Description Number of consecutive TCP keepalive probes that can be sent without receiving a response. After this count is reached, the client or server sending the probes declares that the recipient is offline. You can use this property with either a SQLFire client socket (to determine when a server is offline) or a SQLFire network server socket (to determine when clients go offline). To use this property with a SQLFire thin client, include the jna.jar library in your CLASSPATH. Note: Windows platforms do not support per-socket configuration for keepalive-count. As an alternative, you can configure a system-wide keepalive-count value in some versions of Windows. See http://msdn.microsoft.com/en-us/library/windows/desktop/dd877220%28v=vs.85%29.aspx. Windows Vista and later versions keep this value fixed at 10. Default Value 10 Property Type connection (boot) Prefix sqlfire. keepalive-idle Description TCP keepalive idle timeout in seconds. This is the idle time after which a TCP keepalive probe is sent over the socket to determine if the other side of the socket is alive. You can use this property with either a SQLFire client socket (to determine when a server is offline) or a SQLFire network server socket (to determine when clients go offline). To use this property with a SQLFire thin client, include the jna.jar library in your CLASSPATH. Note: On Solaris platforms prior to r10, system-wide TCP keepalive settings must be changed to larger values (approximately 30 seconds) in order to detect server failures by clients and vice versa. See http://docs.oracle.com/cd/E19082-01/819-2724/fsvdg/index.html. This also applies to other non-Linux, non-Windows platforms. For example, see http://www-01.ibm.com/support/docview.wss?uid=swg21231084. Default Value 20 Property Type connection (boot) Prefix sqlfire. keepalive-interval Description TCP keepalive timeout interval in seconds. This is the time interval to wait between successive TCP keepalive probes if there is no response to the previous probe. You can use this property with either a SQLFire client socket (to determine when a server is offline) or a SQLFire network server socket (to determine when clients go offline). To use this property with a SQLFire thin client, include the jna.jar library in your CLASSPATH. Note: On Solaris platforms prior to r10, system-wide TCP keepalive settings must be changed to larger values (approximately 30 seconds) in order to detect server failures by clients and vice versa. See http://docs.oracle.com/cd/E19082-01/819-2724/fsvdg/index.html. This also applies to other non-Linux, non-Windows platforms. For example, see http://www-01.ibm.com/support/docview.wss?uid=swg21231084. 342 vFabric SQLFire User's Guide Configuration Properties Default Value 1 Property Type connection (boot) Prefix sqlfire. license-serial-number Description Specifies the serial number(s) this distributed system member will use. The distributed member will attempt to activate the license if it acts as a data store. If you have a serial number for the or Global WAN Upgrade, then list it after the vFabric SQLFire Enterprise serial number, separating each with a comma. Use the keyword "dynamic" to specify that the member will attempt to acquire a license from either a vFabric serial number file or a vFabric License Server. Note: You can only use a vFabric License Server you are running SQLFire on a vSphere virtual machine as part of vFabric Suite. The vFabric License Server cannot provide a standalone vFabric SQLFire license, such as a vFabric SQLFire Enterprise license. See Activating vFabric SQLFire Licensing on page 27. Default Value not set Property Type connection (boot) Prefix sqlfire. license-server-timeout Description Specifies the maximum number of milliseconds to wait for a license from a vFabric License Server when attempting to dynamically acquire a license. This timeout is observed when using the keyword "dynamic" for the license-serial-number property. Valid values are in the range of 1000...3600000. See Activating vFabric SQLFire Licensing on page 27. Default Value 10000 Property Type connection (boot) Prefix gemfire. license-working-dir Description The writable directory where this member persists runtime information about licensing. Keep this directory the same between runs for each member so the member can read what it persisted on the last run. See Activating vFabric SQLFire Licensing on page 27. Default Value The member's current working directory as determined by System.getProperty("user.dir") Property Type connection (boot) Prefix gemfire. 343 vFabric SQLFire Reference load-balance Description Specifies whether load balancing is performed for the JDBC client connection. If "false," then no load-balancing is attempted for the connection. Default Value true Property Type connection Prefix n/a locators Description List of locators used by system members. The list must be configured consistently for every member of the distributed system. If the list is empty, locators are not used. For each locator, provide a host name and/or address (separated by ‘@’, if you use both), followed by a port number in brackets. Examples: locators=address1[port1],address2[port2] locators=hostName1@address1[port1],name2@address2[port2] locators=hostName1[port1],name2[port2] Note: On multi-homed hosts, this last notation uses the default address. If you use bind addresses for your locators, explicitly specify the addresses in the locators list—do not use just the hostname. Default Value not set Property Type connection (boot) Prefix gemfire. log-disk-space-limit Description Maximum size in megabytes of all inactive log files combined. If this limit is exceeded, inactive log files are deleted, oldest first, until the total size is within the limit. If set to zero, disk space use is unlimited. Default Value 0 Property Type connection (boot) Prefix gemfire. log-file Description File to to use for writing log messages. If set to null, the default is used. Each member type has its own default output: • application: standard out • locator: locator.log • server: sqlfserver.log Use the sqlfire. prefix for SQLFire members, or use the sqlfire.client prefix for client-side logging. Default Value 344 not set vFabric SQLFire User's Guide Configuration Properties Property Type connection Prefix sqlfire. or sqlfire.client. log-file-size-limit Description The maximum size in megabytes of a log file before it is closed and logging rolls on to a new (child) log file. If set to 0, log rolling is disabled. Default Value 0 Property Type connection (boot) Prefix n/a log-level Description Level of detail of the messages written to the system member’s log. Setting log-level to one of the ordered levels causes all messages of that level and greater severity to be printed. Valid values from lowest to highest are fine, config, info, warning, error, severe, and none. Default Value config Property Type connection (boot) Prefix gemfire. max-num-reconnect-tries Description The maximum reconnection attempts to the distributed system when membership roles are missing. Used when membership attributes specify to disconnect from the distributed system and reconnect in an attempt to regain lost membership roles. Default Value 3 Property Type connection (boot) Prefix gemfire. max-wait-time-reconnect Description The maximum milliseconds to wait for the distributed system to reconnect on each reconnect attempt. Used when membership attributes specify to disconnect from the distributed system and reconnect in an attempt to regain lost membership roles. Default Value 10000 Property Type connection (boot) Prefix gemfire. mcast-address Description Note: This setting controls only peer-to-peer communication and does not apply to client/server or multi-site communication. 345 vFabric SQLFire Reference Address used to discover other members of the distributed system. Only used if mcast-port is non-zero. This attribute must be consistent across the distributed system. Note: Select different multicast addresses and different ports for different distributed systems. Do not just use different addresses. Some operating systems may not keep communication separate between systems that use unique addresses but the same port number. This default multicast address was assigned by IANA ( http://www.iana.org/assignments/multicast-addresses ). Consult the IANA chart when selecting another multicast address to use with SQLFire. Default Value 239.192.81.1 Property Type connection (boot) Prefix gemfire. mcast-flow-control Description Note: This setting controls only peer-to-peer communication. Tuning property for flow-of-control protocol for unicast and multicast no-ack UDP messaging. Compound property made up of three settings separated by commas: byteAllowance, rechargeThreshold, and rechargeBlockMs. Valid values range from these minimums: 10000,0.1,500 to these maximums: no_maximum ,0.5,60000. Default Value 1048576,0.25, 5000 Property Type connection (boot) Prefix gemfire. mcast-port Description Note: This setting controls only peer-to-peer communication and does not apply to client/server or multi-site communication. Port used, along with the mcast-address, for multicast communication with other members of the distributed system. If zero, multicast is disabled for member discovery and distribution. Note: Select different multicast addresses and ports for different distributed systems. Do not just use different addresses. Some operating systems may not keep communication separate between systems that use unique addresses but the same port number. Valid values are in the range 0..65535. Either mcast-port or locators is required for a peer. If mcast-port is specified, do not specify locators or set start-locator. Default Value 10334 Property Type connection (boot) Prefix gemfire. 346 vFabric SQLFire User's Guide Configuration Properties mcast-recv-buffer-size Description Note: This setting controls only peer-to-peer communication and does not apply to client/server or multi-site communication. Size of the socket buffer used for incoming multicast transmissions. You should set this high if there will be high volumes of messages. The default setting is higher than the default OS maximum buffer size on Unix, which should be increased to at least 1 megabyte to provide high-volume messaging on Unix systems. Valid values are in the range 2048.. OS_maximum. Default Value 1048576 Property Type connection (boot) Prefix gemfire. mcast-send-buffer-size Description Note: This setting controls only peer-to-peer communication and does not apply to client/server or multi-site communication. The size of the socket buffer used for outgoing multicast transmissions. Valid values are in the range 2048.. OS_maximum. Default Value 65535 Property Type connection (boot) Prefix gemfire. mcast-ttl Description Note: This setting controls only peer-to-peer communication and does not apply to client/server or multi-site communication. How far multicast messaging goes in your network. Lower settings may improve system performance. A setting of 0 constrains multicast messaging to the machine. Default Value 32 Property Type connection (boot) Prefix gemfire. member-timeout Description Interval, in milliseconds, between two attempts to determine whether another system member is alive. When another member appears to be gone, SQLFire tries to contact it twice before quitting. Valid values are in the range 1000..600000. Default Value 5000 347 vFabric SQLFire Reference Property Type connection (boot) Prefix gemfire. membership-port-range Description The range of ports available for unicast UDP messaging and for TCP failure detection. Specify this value as two integers separated by a minus sign. Different members can use different ranges. SQLFire randomly chooses two unique integers from this range for the member, one for UDP unicast messaging and the other for TCP failure detection messaging. Additionally, the system uniquely identifies the member using the combined host IP address and UDP port number. You may want to restrict the range of ports that SQLFire uses so the product can run in an environment where routers only allow traffic on certain ports. Default Value 1024-65535 Property Type connection (boot) Prefix gemfire. password Description A password for the user name given at boot or connection time. Use this attribute in conjunction with the user attribute. Default Value not set Property Type connection Prefix n/a persist-dd Description Enables or disables disk persistence for the data dictionary. By default, all data stores (SQLFire members booted with host-data=true) set this value to "true" to enable persistence. All SQLFire data stores in the same cluster must use the same persistence setting. When persistence is enabled, if all data stores in a cluster are down, then clients cannot execute DDL statements in the cluster until a data store becomes available. This ensures that the persisent data dictionary can be recovered when the final data store rejoins the cluster. Note: You cannot enable persistence for SQLFire accessors (members that booted with host-data=false). When persist-dd is set to "false," then no tables can be declared as persistent. However, overflow can still be configured if you explicitly define the sys-disk-dir attribute. When a new SQLFire member joins an existing cluster, the data dictionary is obtained either from other members, or it is retrieved from persisted data if the new member is determined to have to most current copy of the data in the cluster. Optimizing Availability and Performance on page 93 provides more information about starting and shutting down SQLFire clusters that utilize disk stores for persistence. Default Value true Property Type connection (boot) 348 vFabric SQLFire User's Guide Configuration Properties Prefix sqlfire. read-timeout Description Defines the read-timeout for a thin-client connection, in seconds. If no response is received after this time, the connection is dropped and SQLFire can attempt to reconnect. Default Value not set Property Type connection Prefix n/a redundancy-zone Description Defines this member's redundancy zone. Used to separate members into different groups for satisfying partitioned table redundancy. If this property is set, SQLFire does not put redundant copies of data in members with the same redundancy zone setting. Default Value not set Property Type connection (boot) Prefix gemfire. secondary-locators Description Provides the address and port number of a secondary SQLFire locator member to use for connecting to the distributed system. The secondary locator address is used to establish an initial connection to SQLFire if the primary locator is not available. Default Value not set Property Type connection Prefix n/a security-log-file Description Used with authentication. The log file for security log messages. If not specified, the member's regular log file is used. Default Value not set Property Type connection (boot) Prefix gemfire. security-log-level Description Used with authentication. Logging level detail for security log messages. Valid values from lowest to highest are fine, config, info, warning, error, severe, and none. Default Value config Property Type connection (boot) 349 vFabric SQLFire Reference Prefix gemfire. security-peer-verifymember-timeout Description Used with authentication. Timeout in milliseconds used by a peer to verify membership of an unknown authenticated peer requesting a secure connection. Default Value 1000 Property Type connection (boot) Prefix gemfire. server-auth-provider Description Specifies the authentication scheme to use for server connections. Possible values are same as those for auth-provider. Default Value Inherits from auth-provider Property Type connection (boot) Prefix sqlfire. server-bind-address Description Note: This setting is only relevant for servers on multi-homed hosts (machines with multiple network cards). Network adapter card a SQLFire server binds to for client/server communication. You can use this to separate the server’s client/server communication from its peer-to-peer communication, spreading the traffic load. Specify the IP address, not the hostname, because each network card may not have a unique hostname. This is a machine-wide attribute used for communication with clients in client/server and multi-site installations. It has no effect on locator location. An empty string (the default) causes the servers to listen on the same card that is used for peer-to-peer communication. This is either the bind-address or, if that is not set, the machine’s default card. Default Value not set Property Type connection (boot) Prefix gemfire. server-groups Description One or more server groups in which the SQLFire member participates. Use a comma-separated list of server group names to supply multiple values. Server groups are used with SQLFire DDL statements, and also for executing data-aware procedures. If you do not use the server-groups attribute, or if you do not specify a value for the attribute, then the SQLFire member is added only to the default server group. The default server group includes all of the SQLFire members that participate in the distributed system. 350 vFabric SQLFire User's Guide Configuration Properties SQLFire members that do not host data (host-data=false) can still participate in server groups in order to provide routing information for data-aware procedures that target specific server groups. Default Value not set Property Type connection (boot) Prefix sqlfire. shutdown Description Stops SQLFire in the current process. A successful shutdown always results in a SQLException indicating that StopsSQLFire has shut down and that there is no longer a connection active. shutdown=true overrides all other attributes that might be specified in the JDBC connection. Default Value false Property Type connection (boot) Prefix n/a single-hop-enabled Description Determines whether a JDBC thin-client driver connection provides single-hop access to data for queries that are distributed to multiple SQLFire members. By default, the thin-client driver provides one-hop or two-hop access to data. See Connect to a SQLFire Server with the Thin Client JDBC Driver on page 123. See also sqlfire.client.single-hop-max-connections on page 359. Default Value false Property Type connection Prefix n/a skip-listeners Description If true, SQLFire does not propagate DML operations to configured DBSynchronizer, AsyncEventListener, or EventCallBack (Writer and Listener) implementations. This is a connection-level property and applies only to DML operations generated by the specific connection that enables the property. Note: This property does not affect WAN replication using a configured gateway. SQLFire always propagates DML operations to an enabled WAN site. Default Value false Property Type connection Prefix n/a socket-buffer-size Description Receive buffer sizes in bytes of the TCP/IP connections used for data transmission. To minimize the buffer size allocation needed for distributing large, serializable messages, the messages are sent in chunks. This 351 vFabric SQLFire Reference setting determines the size of the chunks. Larger buffers can handle large messages more quickly, but take up more memory. Default Value 32768 Property Type connection (boot) Prefix gemfire. socket-lease-time Description The time, in milliseconds, that a thread can have exclusive access to a socket it is not actively using. A value of zero causes socket leases to never expire. This property is ignored if conserve-sockets is true. Valid values are in the range 0..600000. Default Value 60000 Property Type connection (boot) Prefix gemfire. sqlfire.auth-ldap-search-base Description Use this property to limit the search space used when SQLFire verifies a user login ID. Specify the name of the context or object to search, that is a parameter to javax.naming.directory.DirContext.search(). For example: ou=ldapTesting,dc=vmware,dc=com By default, SQLFire tries to bind the anonymous user for searching when you configure sqlfire.auth-ldap-search-base. If your LDAP server does not support anonymous binding, also configure sqlfire.auth-ldap-search-dn and sqlfire.auth-ldap-search-pw. Default Value not set Property Type system Prefix n/a sqlfire.auth-ldap-search-dn Description If the LDAP server does not allow anonymous binding (or if this functionality is disabled), specify the user distinguished name (DN) to use for binding to the LDAP server for searching. For example: uid=guest,o=vmware.com Default Value Null Property Type system Prefix n/a sqlfire.auth-ldap-search-filter Description Specifies a user's objectClass, used to narrow the LDAP search. For example: objectClass=person 352 vFabric SQLFire User's Guide Configuration Properties See Guest Access to Search for DNs on page 254. Default Value (&(objectClass=inetOrgPerson)(uid=%USERNAME%)) Property Type system Prefix n/a sqlfire.auth-ldap-search-pw Description The password for the guest user DN, used for looking up the DN (see sqlfire.auth-ldap-search-dn on page 352). For example: guestPassword Default Value Null Property Type system Prefix n/a sqlfire.auth-ldap-server Description The URI of the LDAP server (beginning with either ldap:// or ldaps://). Default Value not set Property Type system Prefix n/a sqlfire.authz-default-connection-mode Description If authorization is enabled, then this property sets the access mode for all users that are not listed in the sqlfire.authz-full-access-users or sqlfire.authz-read-only-access-users properties. Configure this property only if you do not intend to use the GRANT and REVOKE commands to manage privileges on SQL objects. The possible values are NOACCESS, READONLYACCESS, and FULLACCESS. Keep in mind that using this property overrides any fine-grained privileges that are granted using the GRANT statement. For example, if you set this property to NOACCESS, then any user that is not listed under sqlfire.authz-full-access-users or sqlfire.authz-read-only-access-users has no access to SQLFire tables. You cannot use GRANT to give such a user additional privileges. Default Value If you do not configure this property, then all users have full access (read/write privileges) unless the user is listed in sqlfire.authz-read-only-access-users or have been given specific permissions with GRANT and REVOKE. Property Type system Prefix n/a 353 vFabric SQLFire Reference sqlfire.authz-full-access-users Description Defines the list of user names that have full access to SQL objects. Users that are listed in sqlfire.authz-full-access-users have full access regardless of whether specific privileges were taken away using the REVOKE statement. Default Value not set Property Type system Prefix n/a sqlfire.authz-read-only-access-users Description Defines the list of user names that have read-only access to SQL objects. This property is generally used when sqlfire.authz-default-connection-mode is set to FULLACCESS. Configure this property only if you do not intend to use the GRANT and REVOKE commands to manage privileges on SQL objects. Any users that are listed in sqlfire.authz-read-only-access-users have read-only access, regardless of whether any additional privileges were granted using the GRANT statement. Default Value not set Property Type system Prefix n/a sqlfire.sql-authorization Description Enables or disables authorization in SQLFire. See Configuring User Authorization on page 258. The default value of this property is "false." However, if you use the -auth-provider option to specify a client authentication mechanism when starting a SQLFire member, SQL authorization is enabled by default. Default Value false Property Type system Prefix n/a sqlfire.datadictionary.allow-startup-errors Description Enables a SQLFire member to start up, ignoring DDL statements that fail during member initialization. This property enables you to resolve startup problems manually, after forcing the member to start. Typical DDL initialization problems occur when a required disk store file is unavailable, or when SQLFire cannot initialize a DBSynchronizer configuration due to the external RDBMS being unavailable. Use sqlfire.datadictionary.allow-startup-errors to drop and recreate the disk store or DBSynchronizer configuration after startup. See also Member Startup Problems on page 775. Default Value false Property Type system Prefix n/a 354 vFabric SQLFire User's Guide Configuration Properties sqlfire.drda.host Description Network interface on which the network server listens. This property allows multiple members of a Network Server to run on a single machine, each using its own unique host:port combination. If the property is set to 0.0.0.0, the Network Server listens on all interfaces. Ensure that you are running under the security manager and that user authorization is enabled before you enable remote connections with this property Default Value The Network Server listens only on the loopback address (localhost). Property Type system Prefix n/a sqlfire.drda.keepAlive Description If true, SQLFire attempts to clean up disconnected clients. The idle time is two hours by default. Default Value true Property Type system Prefix n/a sqlfire.drda.logConnections Description Specifies whether to log network client connections and disconnections. This setting can be enabled dynamically using NetworkInterface as well. Default Value false Property Type system Prefix n/a sqlfire.drda.maxThreads Description Maximum number of connection threads that the Network Server allocates. If the maximum number of threads are allocated, then connections are shared using the sqlfire.drda.timeSlice property to switch between connections. This setting can be enabled using NetworkInterface as well, but the Network Server must be restarted for the change to take effect. Default Value 0 (unlimited) Property Type system Prefix n/a sqlfire.drda.minThreads Description Minimum number of connection threads that the Network Server allocates. This setting can be enabled using NetworkInterface as well, but the Network Server must be restarted for the change to take effect. 355 vFabric SQLFire Reference Default Value On-demand allocation. Property Type system Prefix n/a sqlfire.drda.portNumber Description Port number to use. Default Value 1527 Property Type system Prefix n/a sqlfire.drda.securityMechanism Description Restricts client connections based on the security mechanism. If set to a valid mechanism, then only those connections with the specified mechanism are allowed. If no value is set, then connections with any mechanism are allowed. Possible values are: • USER_ONLY_SECURITY • CLEAR_TEXT_PASSWORD_SECURITY • ENCRYPTED_USER_AND_PASSWORD_SECURITY • STRONG_PASSWORD_SUBSTITUTE_SECURITY Default Value None Property Type system Prefix n/a sqlfire.drda.sslMode Description Determines whether the client connection is encrypted or not, and whether certificate-based peer authentication is enabled. Possible values are Off, Basic, and peerAuthentication Default Value Off Property Type system Prefix n/a sqlfire.drda.streamOutBufferSize Description Configures the size of the buffer used for streaming BLOB/CLOB data from the server to a client. If the configured size is 0 or less, then the buffer is not created. Default Value 0 Property Type system Prefix n/a 356 vFabric SQLFire User's Guide Configuration Properties sqlfire.drda.timeSlice Description Number of milliseconds that each connection uses before yielding to another connection. This property is effective only if sqlfire.drda.maxThreads is set greater than zero. The server must be restarted for changes to take effect. Default Value 0 Property Type system Prefix n/a sqlfire.drda.trace Description Enables tracing for the client session. This setting can be enabled dynamically using NetworkInterface as well. Default Value false Property Type system Prefix n/a sqlfire.drda.traceAll Description Enables tracing for all client sessions. This setting can be enabled dynamically using NetworkInterface as well. Default Value false Property Type system Prefix n/a sqlfire.drda.traceDirectory Description Location of the tracing directory on the server. This setting can be enabled using NetworkInterface as well, but the Network Server must be restarted for the change to take effect. Default Value Uses the sqlfire.system.home property (if set). Otherwise, uses the current directory. Property Type system Prefix n/a sqlfire.history Description The path and filename in which the sqlf utility stores a list of the commands executed during an interactive sqlf session. Specify this system property in the JAVA_ARGS environment variable before you execute sqlf (for example, JAVA_ARGS="-Dsqlf.history=path-to-file"). Specify an empty string value to disable recording a history of commands. See sqlf Interactive Commands on page 449. Default Value %UserProfile%\.sqlf.history (Windows) $HOME/.sqlf.history (Linux) 357 vFabric SQLFire Reference Property Type system Prefix n/a sqlfire.language.permissionsCacheSize Description The size of the permissions that SQLFire caches in m memory for faster lookup performance. This property cannot be overridden using a system property. Specify the number of entries to cache. Default Value 64 Property Type connection (boot) Prefix n/a sqlfire.language.spsCacheSize Description The size of the stored prepared statement descriptor cache that SQLFire uses for looking up definitions. Specify the number of entries to cache. Default Value 32 Property Type connection (boot) Prefix n/a sqlfire.language.statementCacheSize Description The size of the precompiled statement cache for DML statements. Specify the number of entries to cache. Default Value 100 Property Type connection (boot) Prefix n/a sqlfire.language.tableDescriptorCacheSize Description The size of table descriptors that SQLFire caches in memory for faster lookup performance. This property cannot be overridden using a system property. Specify the number of entries to cache. Default Value 64 Property Type connection (boot) Prefix n/a sqlfire.max-lock-wait Description Maximum time in milliseconds that a DDL statement waits for a distributed lock on the data dictionary or a table. Default Value 300000 Property Type connection (boot) Prefix n/a 358 vFabric SQLFire User's Guide Configuration Properties sqlfire.properties Description Overrides the default lookup for application file properties in the file named 'sqlfire.properties.' Default Value sqlfire.properties Property Type system Prefix n/a sqlfire.query-cancellation-interval Description After used memory used passes a critical limit, SQLFire begins cancelling queries to free memory. This attribute specifies the period in milliseconds after which SQLFire cancels a query during periods of critical memory usage. With the default value, SQLFire cancels a query every 100 milliseconds when necessary to free memory. Default Value 100 Property Type connection (boot) Prefix n/a sqlfire.security. Properties (prefix) Description All properties that are prefixed with sqlfire.security. are propagated to the plug-in implementation of UserAuthenticator on page 478 and CredentialInitializer on page 478. Default Value not set Property Type connection (boot) Prefix sqlfire.security. sqlfire.client.single-hop-max-connections Description If sqlfire.client.single-hop-max-connections is set to true, then this system property specifies the maximum number of single-hop client connections that a server can support. The default value of 5 creates enough connections for 5 single-hop clients to distribute queries to other SQLFire members in the cluster. Set this value to the maximum number of single-hop clients that you want to support at one time. Note that the actual number of connections that may be created for single-hop clients is determined by the number of members in the SQLFire distributed system. For example, if the SQLFire cluster has 10 members, then the default sqlfire.client.single-hop-max-connections setting of 5 means that a maximum of 50 connections could be created for single-hop access (5 simultaneous single-hop clients connecting to all servers in the cluster). However, the actual connection resources are created only when necessary. See Connect to a SQLFire Server with the Thin Client JDBC Driver on page 123. Default Value 5 Property Type system Prefix n/a 359 vFabric SQLFire Reference sqlfire.stream.error.logSeverityLevel Description Logging for messages of different severity levels. Possible values for this property are: • 0—NO_APPLICABLE_SEVERITY occurs only when the system was unable to determine the severity. • 10000—WARNING_SEVERITY includes SQLWarnings. • 20000—STATEMENT_SEVERITY includes errors that cause only the current statement to be aborted. • 30000—TRANSACTION_SEVERITY includes errors that cause the current transaction to be aborted. • 40000—SESSION_SEVERITY includes errors that cause the current connection to be closed. • 45000—DATABASE_SEVERITY includes errors that cause the current database to be closed. • 50000—SYSTEM_SEVERITY includes internal errors that cause the system to shut down. Default Value 0 Property Type connection (boot) Prefix n/a sqlfire.storage.tempDirectory Description The temporary directory for overflowing intermediate data. For example, this directory is used during join processing to temporarily store sorted data in multiple files. Default Value not set Property Type connection (boot) Prefix n/a sqlfire.system.home Description Specifies the SQLFire home directory. Any relative paths in the system are accessed using this property value. Default Value not set Property Type connection (boot) Prefix n/a ssl Description Boolean indicating whether to use SSL for this connection. Default Value false Property Type connection Prefix n/a ssl-ciphers Description 360 Used for SSL security. A space-separated list of the valid SSL ciphers for this connection. A setting of 'any' uses any ciphers that are enabled by default in the configured JSSE provider. vFabric SQLFire User's Guide Configuration Properties Default Value any Property Type connection (boot) Prefix gemfire. ssl-enabled Description Used for SSL security. Boolean indicating whether to use SSL for member communications. A true setting requires the use of locators. This attribute must be consistent across the distributed system. Default Value false Property Type connection (boot) Prefix gemfire. ssl-protocols Description Used for SSL security. A space-separated list of the valid SSL protocols for this connection. A setting of 'any' uses any protocol that is enabled by default in the configured JSSE provider. Default Value any Property Type connection (boot) Prefix gemfire. ssl-require-authentication Description Used for SSL security. Boolean indicating whether to require authentication for member communication. Default Value true Property Type connection (boot) Prefix gemfire. start-locator Description If set, automatically starts a locator in the current process when the member connects to the distributed system and stops the locator when the member disconnects. To use, specify the locator with an optional address or host specification and a required port number, in one of these formats: start-locator=address[port1] start-locator=port1 If you only specify the port, the address assigned to the member is used for the locator. If not already there, this locator is automatically added to the list of locators in this set of SQLFire properties. If you set start-locator, do not also specify mcast-port. Default Value not set 361 vFabric SQLFire Reference Property Type connection (boot) Prefix gemfire. statistic-archive-file Description The file to which the running system member writes statistic samples. An empty string disables archiving. Adding .gz suffix to the file name causes it to be compressed. Default Value not set Property Type connection (boot) Prefix gemfire. statistic-sample-rate Description Boot property that specifies how often to sample statistics, in milliseconds. Valid values are in the range 100..60000. Default Value 1000 Property Type connection (boot) Prefix gemfire. statistic-sampling-enabled Description Determines whether to collect and archive statistics on the member. Turning statistics sampling off saves on resources, but it also takes away potentially valuable information for ongoing system tuning and about unexpected system problems. Default Value false Property Type connection (boot) Prefix gemfire. sync-commits Description Determines whether second-phase commit actions occur in the background for the current connection, or whether the connection waits for second-phase commit actions to complete. By default (sync-commits=false) SQLFire performs second-phase commits in the background, but ensures that the connection that issued the transaction only sees completed results. This means that other threads or connections may see different results until the second-phase commit actions complete. Using sync-commits=true ensures that the current thin client or peer client connection waits until all second-phase commit actions complete. Default Value false Property Type connection (boot) Prefix n/a 362 vFabric SQLFire User's Guide Configuration Properties sys-disk-dir Description Specifies the base path of the default disk store. This directory also holds the datadictionary subdirectory, which stores the persistent data dictionary. Other SQLFire features also use this directory for storing files. For example, gateway queue overflow and overflow tables use this attribute by default. You can override sys-disk-dir for table overflow using options in a table's CREATE Default Value The SQLFire working directory. Property Type connection (boot) Prefix sqlfire. TABLE statement. tcp-port Description TCP port to listen on for cache communications. If set to zero, the operating system selects an available port. Each process on a machine must have its own TCP port. Some operating systems restrict the range of ports usable by non-privileged users, and using restricted port numbers can cause runtime errors in SQLFire startup. Valid values are in the range 0..65535. Default Value 0 Property Type connection (boot) Prefix gemfire. udp-fragment-size Description The maximum fragment size, in bytes, for transmission over UDP unicast or multicast sockets. Smaller messages are combined, if possible, for transmission up to the fragment size setting. Valid values are in the range 1000..60000. Default Value 60000 Property Type connection (boot) Prefix gemfire. udp-recv-buffer-size Description Size of the socket buffer used for incoming UDP point-to-point transmissions. If disable-tcp is false, a reduced buffer size of 65535 is used by default. The default setting of 1048576 is higher than the default OS maximum buffer size on Unix, which should be increased to at least 1MB to provide high-volume messaging on Unix systems. Valid values are in the range 2048.. OS_maximum. Default Value 1048576 Property Type connection (boot) Prefix gemfire. 363 vFabric SQLFire Reference udp-send-buffer-size Description Size of the socket buffer used for outgoing UDP point-to-point transmissions. Valid values are in the range 2048..OS_maximum. Default Value 65535 Property Type connection (boot) Prefix gemfire. user Description The user name for the member or connection. A valid user name and password are required when user authentication is turned on. Use this attribute in conjunction with the password attribute. Default Value not set Property Type connection Prefix n/a writable-working-dir Description Writable directory where this member should persist runtime information. Keep this directory the same between runs for each member so the member application can read what it persisted on the last run. Default Value member's current working directory Property Type connection (boot) Prefix gemfire. 364 vFabric SQLFire User's Guide Chapter 52 JDBC API Information about the SQLFire implementation of java.sql classes, interfaces, and methods. Core JDBC Classes, Interfaces, and Methods The following sections describe the SQLFire implementation of selected JDBC classes, interfaces, and methods. java.sql.BatchUpdateException Class This class is an extension of SQLException that is thrown if a failure occurs during execution of a batch statement. Such a failure can occur with the batch operation of the JDBC Statement, PreparedStatement or CallableStatement classes. Exceptions caused by other batch elements are maintained in the getNextException() chain, as they are for SQLExceptions. This class adds one new method to the SQLException class named getUpdateCounts(). This method returns an array of update counts of the statements that executed successfully before the exception occurred. java.sql.Connection Interface A SQLFire Connection object is not garbage-collected until all other JDBC objects created from that connection are explicitly closed or are themselves garbage-collected. Once the connection is closed, no further JDBC requests can be made against objects created from the connection. Do not explicitly close the Connection object until you no longer need it for executing statements. A session-severity or higher exception causes the connection to close and all other JDBC objects against it to be closed. java.sql.Connection.setTransactionIsolation Method Only java.sql.Connection.TRANSACTION_NONE, and java.sql.Connection.TRANSACTION_READ_COMMITTED transaction isolation levels are available in SQLFire. TRANSACTION_NONE is the default isolation level. Changing the current isolation for the connection with setTransactionIsolation commits the current transaction and begins a new transaction. Note: Special Note on TRANSACTION_NONE SQLFire provides atomicity and thread safety for row-level operations even in TRANSACTION_NONE isolation level. For more details about transaction isolation, see Using Distributed Transactions in Your Applications on page 157. 365 vFabric SQLFire Reference Connection Functionality Not Supported java.sql.Connection.setReadOnly and isReadOnly methodsRead-only connections are not supported in SQLFire. Calling setReadOnly with a value of true throws a "Feature not supported" exception, and isReadOnly always returns false. Connections to XA DataSources (javax.sql.XADataSource) are not supported in this release of SQLFire. SQLFire does not use catalog names. In addition, the following optional methods raise "Feature not supported" exceptions: • createArrayOf( java.lang.String, java.lang.Object[] ) • createNClob( ) • createSQLXML( ) • createStruct( java.lang.String, java.lang.Object[] ) • getTypeMap( ) • setTypeMap( java.util.Map ) java.sql.DatabaseMetaData Interface The following sections describe java.sql.DatabaseMetaData functionality in SQLFire. • DatabaseMetaData Result Sets on page 366 • java.sql.DatabaseMetaData.getProcedureColumns Method on page 366 • Parameters to getProcedureColumns on page 366 • java.sql.DatabaseMetaData.getBestRowIdentifier Method on page 367 DatabaseMetaData Result Sets DatabaseMetaData result sets do not close the result sets of other statements, even when auto-commit is set to true. DatabaseMetaData result sets are closed if a user performs any other action on a JDBC object that causes an automatic commit to occur. If you need the DatabaseMetaData result sets to be accessible while executing other actions that would cause automatic commits, turn off auto-commit with setAutoCommit(false). java.sql.DatabaseMetaData.getProcedureColumns Method SQLFire supports Java procedures and allows you to call Java procedures within SQL statements. SQLFire returns information about the parameters in the getProcedureColumns call and returns information for all Java procedures defined by CREATE PROCEDURE. getProcedureColumns returns a ResultSet. Each row describes a single parameter or return value. Parameters to getProcedureColumns The JDBC API defines the following parameters for the getProcedureColumns method call. 366 catalog Always use null for this parameter in SQLFire. schemaPattern Java procedures have a schema. procedureNamePattern A String object representing a procedure name pattern. column-Name-Pattern A String object representing the name pattern of the parameter names or return value names. Java procedures have parameter names matching those vFabric SQLFire User's Guide JDBC API defined in the CREATE PROCEDURE statement. Use "%" to find all parameter names. Columns in the ResultSet Returned by getProcedureColumns Columns in the ResultSet returned by getProcedureColumns are as described by the API. Further details for some specific columns: PROCEDURE_CAT Always "null" in SQLFire. PROCEDURE_SCHEM Schema for a Java procedure. PROCEDURE_NAME Name of the procedure. COLUMN_NAME Name of the parameter. See column-Name-Pattern under Parameters to getProcedureColumns on page 366. COLUMN_TYPE Short indicating what the row describes. It is always DatabaseMetaData.procedureColumnIn for method parameters, unless the parameter is an array. If so, it is DatabaseMetaData.procedureColumnInOut. It always returns DatabaseMetaData.procedureColumnReturn for return values. TYPE_NAME SQLFire-specific name for the type. NULLABLE Always returns DatabaseMetaData.procedureNoNulls for primitive parameters and DatabaseMetaData.procedureNullable for object parameters REMARKS String describing the java type of the method parameter. COLUMN_DEF String describing the default value for the column (may be null). SQL_DATA_TYPE Reserved by JDBC spec for future use. SQL_DATETIME_SUB Reserved by JDBC spec for future use. CHAR_OCTET_LENGTH Maximum length of binary and character based columns (or any other datatype the returned value is a NULL). ORDINAL_POSITION Ordinal position, starting from 1, for the input and output parameters for a procedure. IS_NULLABLE String describing the parameter's nullability (YES means parameter can include NULLs, NO means it cannot). SPECIFIC_NAME Name that uniquely identifies this procedure within its schema. METHOD_ID SQLFire-specific column. PARAMETER_ID SQLFire-specific column. java.sql.DatabaseMetaData.getBestRowIdentifier Method The java.sql.DatabaseMetaData.getBestRowIdentifier method looks for identifiers in the following order: • A primary key on the table. • A unique constraint or unique index on the table. • All of the columns in the table. This order might not return a unique row. 367 vFabric SQLFire Reference Note: If the java.sql.DatabaseMetaData.getBestRowIdentifier method does not find a primary key, unique constraint, or unique index, the method must look for identifiers in all of the columns in the table. When the method looks for identifiers this way, the method will always find a set of columns that identify a row. However, a unique row might not be identified if there are duplicate rows in the table. java.sql.Driver Interface The java.sql.Driver.getPropertyInfo method method returns a DriverPropertyInfo object. In a SQLFire system, this consists of an array of database connection URL attributes. (See Configuration Properties on page 327.) To get the DriverPropertyInfo object, request the JDBC driver from the driver manager: String url = "jdbc:sqlfire:"; Properties info = new Properties(); java.sql.DriverManager.getDriver(url).getPropertyInfo(url, info); java.sql.DriverManager.getConnection Method A Java application using the JDBC API establishes a connection to a distributed system by obtaining a Connection object. The standard way to obtain a Connection object is to call the method DriverManager.getConnection, which takes a String containing a connection URL. A JDBC connection URL (uniform resource locator) identifies a source of data. DriverManager.getConnection can take one argument besides a connection URL, a Properties object. You can use the Properties object to set connection URL attributes. You can also supply strings representing user names and passwords. When they are supplied, SQLFire checks whether they are valid for the current system if user authentication is enabled. User names are passed to SQLFire as authorization identifiers, which determine whether the user is authorized for access to the database and determine the default schema. When the connection is established, if no user is supplied, SQLFire sets the default schema to APP. If a user is supplied, the default schema is the same as the user name. SQLFire Connection URL Syntax A SQLFire connection URL consists of the connection URL protocol (jdbc:) followed by the subprotocol (sqlfire:) and then optional attributes. Syntax of Connection URLs for peer-clients For applications that run in a peer-client, the syntax of the connection URL is *jdbc:sqlfire:_[;attributes]*_* jdbc:sqlfire In JDBC terminology, sqlfire is the subprotocol for connecting to a GemFire distributed system. The subprotocol is always sqlfire and does not vary. attributes Specify 0 or more connection URL attributes as detailed in Configuration Properties on page 327. Additional SQL Syntax SQLFire also supports the following SQL standard syntax to obtain a reference to the current connection in a server-side JDBC routine: *jdbc:default:connection* java.sql.PreparedStatement Interface SQLFire provides all required JDBC type conversions and additionally allows use of the individual setXXX methods for each type as if a setObject(Value, JDBCTypeCode) invocation were made. This means 368 vFabric SQLFire User's Guide JDBC API that setString can be used for any built-in target type. Cursors are not supported in SQLFire; setCursorName method throws an unsupported feature exception. Prepared Statements and Streaming Columns setXXXStream requests stream data between the client and the server. JDBC allows an IN parameter to be set to a Java input stream for passing in large amounts of data in smaller chunks. When the statement is run, the JDBC driver makes repeated calls to this input stream. SQLFire supports the three types of streams that the JDBC API provides: • setBinaryStream Use for streams that contain uninterpreted bytes. • setAsciiStream Use for streams that contain ASCII characters. • setUnicodeStream Use for streams that contain Unicode characters. The stream object passed to these three methods can be either a standard Java stream object or the user's own subclass that implements the standard java.io.InputStream interface. According to the JDBC standard, streams can be stored only in columns with the data types shown in the following table. Streamable JDBC Data Types Column Data Type Corresponding Java Type AsciiStream UnicodeStream BinaryStream CLOB java.sql.Clob x x ' CHAR ' x x ' VARCHAR ' x x ' LONGVARCHAR ' X X ' BINARY ' x x x BLOB java.sql.Blob x x x VARBINARY ' x x x LONGVARBINARY ' x x X Note: • A large X indicates the preferred target data type for the type of stream. See Mapping java.sql.Types to SQL Types on page 370. • If the stream is stored in a column of a type other than LONG VARCHAR or LONG VARCHAR FOR BIT DATA, the entire stream must be able to fit into memory at one time. Streams stored in LONG VARCHAR and LONG VARCHAR FOR BIT DATA columns do not have this limitation. • Streams cannot be stored in columns of the other built-in data types or columns of user-defined data types. Example The following example shows how a user can store a streamed java.io.File in a LONG VARCHAR column: Statement s = conn.createStatement(); s.executeUpdate("CREATE TABLE atable (a INT, b LONG VARCHAR)"); conn.commit(); java.io.File file = new java.io.File("derby.txt"); int fileLength = (int) file.length(); // first, create an input stream java.io.InputStream fin = new java.io.FileInputStream(file); PreparedStatement ps = conn.prepareStatement("INSERT INTO atable VALUES (?, 369 vFabric SQLFire Reference ?)"); ps.setInt(1, 1); // set the value of the input parameter to the input stream ps.setAsciiStream(2, fin, fileLength); ps.execute(); conn.commit(); java.sql.ResultSet Interface Do not assume any implicit ordering of result set rows. If you require ordering, use an ORDER BY clause. java.sql.SavePoint Class This release of SQLFire does not support SavePoints. java.sql.SQLException Class SQLExceptions that are thrown by SQLFire do not always match the Exception that a Derby database would throw. The getSQLState() method on SQLException may also return a different value in some cases. java.sql.Statement Class SQLFire does not implement the setEscapeProcessing method of java.sql.Statement. In addition, the cancel method raises a "Feature not supported" exception. ResultSet Objects An error that occurs when a SELECT statement is first executed prevents a ResultSet object from being opened on it. The same error does not close the ResultSet if it occurs after the ResultSet is opened. For example, a divide-by-zero error that occurs while the executeQuery method is called on a java.sql.Statement or java.sql.PreparedStatement throws an exception and returns no result set at all, while if the same error occurs while the next method is called on a ResultSet object, it does not close the result set. Errors can occur when a ResultSet is first being created if the system partially executes the query before the first row is fetched. This errors can occur on any query that uses more than one table and on queries that use aggregates, GROUP BY, ORDER BY, DISTINCT, INTERSECT, EXCEPT, or UNION. (See SQL Language Limitations on page 765.) Closing a Statement causes all open ResultSet objects on that statement to be closed as well.The cursor name for the cursor of a ResultSet can be set before the statement is executed. However, once it is executed, the cursor name cannot be altered. javax.sql.XADataSource This release of SQLFire does not support javax.sql.XADataSource. Mapping java.sql.Types to SQL Types In SQLFire, the java.sql.Types are mapped to SQL data types. The following table shows the SQLFire mapping of types. 370 java.sql.Types type SQL type BIGINT BIGINT BINARY CHAR FOR BIT DATA BLOB BLOB vFabric SQLFire User's Guide JDBC API java.sql.Types type SQL type CHAR CHAR CLOB CLOB DATE DATE DECIMAL DECIMAL DOUBLE DOUBLE PRECISION FLOAT DOUBLE PRECISION(2) INTEGER INTEGER LONGVARBINARY LONG VARCHAR FOR BIT DATA LONGVARCHAR LONG VARCHAR NULL Not a data type; always a value of a particular type NUMERIC DECIMAL REAL REAL SMALLINT SMALLINT TIME TIME TIMESTAMP TIMESTAMP VARBINARY VARCHAR FOR BIT DATA VARCHAR VARCHAR JDBC Escape Syntax JDBC provides a way of smoothing out some of the differences in the way different DBMS vendors implement SQL. This is called escape syntax. Escape syntax signals that the JDBC driver, which is provided by a particular vendor, scans for any escape syntax and converts it into the code that the particular database understands. This makes escape syntax DBMS-independent. A JDBC escape clause begins and ends with curly braces. A keyword always follows the opening curly brace: { keyword } Note: SQLFire returns the SQL unchanged in the Connection.nativeSQL call, since the escape syntax is native to SQL. In addition, it is unnecessary to call Statement.setEscapeProcessing for this reason. SQLFire supports only the following JDBC escape keywords, which are case-insensitive. JDBC Escape Keyword for Call Statements This syntax is supported for a java.sql.Statement and a java.sql.PreparedStatement in addition to a CallableStatement. 371 vFabric SQLFire Reference Syntax {call statement } -- Call a Java procedure { call TOURS.BOOK_TOUR(?, ?) } JDBC Escape Syntax for LIKE Clauses The percent sign % and underscore _ are metacharacters within SQL LIKE clauses. JDBC provides syntax to force these characters to be interpreted literally. The JDBC clause immediately following a LIKE expression allows you to specify an escape character: Syntax WHERE CharacterExpression [ NOT ] LIKE CharacterExpressionWithWildCard { ESCAPE 'escapeCharacter' } -- find all rows in which a begins with the character "%" SELECT a FROM tabA WHERE a LIKE '$%%' {escape '$'} -- find all rows in which a ends with the character "_" SELECT a FROM tabA WHERE a LIKE '%=_' {escape '='} Note: ? is not permitted as an escape character if the LIKE pattern is also a dynamic parameter (?). In some languages, a single character consists of more than one collation unit (a 16-bit character). The escapeCharacter used in the escape clause must be a single collation unit in order to work properly. You can also use the escape character sequence for LIKE without using JDBC's curly braces; see Boolean Expressions on page 559. JDBC Escape Syntax for fn Keyword You can specify functions in JDBC escape syntax, by using the fn keyword. Syntax {fn functionCall} where functionCall is the name of one of the following scalar functions: abs Returns the absolute value of a number. abs(NumericExpression) The JDBC escape syntax {fn abs(NumericExpression)} is equivalent to the built-in syntax. For more information, see ABS or ABSVAL function on page 569. 372 vFabric SQLFire User's Guide JDBC API acos Returns the arc cosine of a specified number. acos(number) The JDBC escape syntax {fn acos(number)} is equivalent to the built-in syntax ACOS(number). For more information, see ACOS function on page 569. asin Returns the arc sine of a specified number. asin(number) The JDBC escape syntax {fn asin(number)} is equivalent to the built-in syntax ASIN(number). For more information, see ASIN function on page 569. atan Returns the arc tangent of a specified number. atan(number) The JDBC escape syntax {fn atan(number)} is equivalent to the built-in syntax ATAN(number). For more information, see ATAN function on page 570. ceiling Rounds the specified number up, and returns the smallest number that is greater than or equal to the specified number. ceiling(number) The JDBC escape syntax {fn ceiling(number)} is equivalent to the built-in syntax CEILING(number). For more information, see CEIL or CEILING function on page 576. concat Returns the concatenation of character strings. concat(CharacterExpression, CharacterExpression) Character string formed by appending the second string to the first string. If either string is null, the result is NULL. The JDBC escape syntax {fn concat (CharacterExpression, CharacterExpression) is equivalent to the built-in syntax { CharacterExpression || CharacterExpression }. For more information, see Concatenation operator on page 579. cos Returns the cosine of a specified number. cos(number) The JDBC escape syntax {fn cos(number)} is equivalent to the built-in syntax COS(number). For more information, see COS function on page 579. degrees Converts a specified number from radians to degrees. degrees(number) The JDBC escape syntax {fn degrees(number)} is equivalent to the built-in syntax DEGREES(number). For more information, see DEGREES function on page 585. 373 vFabric SQLFire Reference exp Returns e raised to the power of the specified number. exp(number) The JDBC escape syntax {fn exp(number)} is equivalent to the built-in syntax EXP(number). For more information, see EXP function on page 586. floor Rounds the specified number down, and returns the largest number that is less than or equal to the specified number. floor(number) The JDBC escape syntax {fn floor(number)} is equivalent to the built-in syntax FLOOR(number). For more information, see FLOOR function on page 586. locate Returns the position in the second CharacterExpression of the first occurrence of the first CharacterExpression. Searches from the beginning of the second CharacterExpression, unless the startIndex parameter is specified. locate(CharacterExpression,CharacterExpression [, startIndex] ) The JDBC escape syntax {fn locate(CharacterExpression,CharacterExpression [, startIndex] )} is equivalent to the built-in syntax. For more information, see LOCATE function on page 589. log Returns the natural logarithm (base e) of the specified number. log(number) The JDBC escape syntax {fn log(number)} is equivalent to the built-in syntax LOG(number). For more information, see LN or LOG function on page 588. log10 Returns the base-10 logarithm of the specified number. log10(number) The JDBC escape syntax {fn log10(number)} is equivalent to the built-in syntax LOG10(number). For more information, see LOG10 function on page 589. mod Returns the remainder (modulus) of argument 1 divided by argument 2. The result is negative only if argument 1 is negative. mod(integer_type, integer_type) For more information, see MOD function on page 592. pi Returns a value that is closer than any other value to pi. pi() The JDBC escape syntax {fn pi()} is equivalent to the built-in syntax PI(). For more information, see PI function on page 593. 374 vFabric SQLFire User's Guide JDBC API radians Converts a specified number from degrees to radians. radians(number) The JDBC escape syntax {fn radians(number)} is equivalent to the built-in syntax RADIANS(number). For more information, see RADIANS function on page 593. sin Returns the sine of a specified number. sin(number) The JDBC escape syntax {fn sin(number)} is equivalent to the built-in syntax SIN(number). For more information, see SIN function on page 595. sqrt Returns the square root of floating point number. sqrt(FloatingPointExpression) The JDBC escape syntax {fn sqrt (FloatingPointExpression)} is equivalent to the built-in syntax. For more information, see SQRT function on page 597. substring Forms a character string by extracting length characters from the CharacterExpression beginning at startIndex. The index of the first character in the CharacterExpression is 1. substring(CharacterExpression, startIndex, length) tan Returns the tangent of a specified number. tan(number) The JDBC escape syntax {fn tan(number)} is equivalent to the built-in syntax TAN(number). For more information, see TAN function on page 598. TIMESTAMPADD Use the TIMESTAMPADD function to add the value of an interval to a timestamp. The function applies the integer to the specified timestamp based on the interval type and returns the sum as a new timestamp. You can subtract from the timestamp by using negative integers. The TIMESTAMPADD is a JDBC escaped function, and is only accessible by using the JDBC escape function syntax. TIMESTAMPADD( interval, integerExpression, timestampExpression ) To perform TIMESTAMPADD on dates and times, it is necessary to convert the dates and times to timestamps. Dates are converted to timestamps by putting 00:00:00.0 in the time-of-day fields. Times are converted to timestamps by putting the current date in the date fields. You should not put a datetime column inside of a timestamp arithmetic function in WHERE clauses because the optimizer will not use any index on the column. 375 vFabric SQLFire Reference TIMESTAMPDIFF Use the TIMESTAMPDIFF function to find the difference between two timestamp values at a specified interval. For example, the function can return the number of minutes between two specified timestamps. The TIMESTAMPDIFF is a JDBC escaped function, and is only accessible by using the JDBC escape function syntax. TIMESTAMPDIFF( interval, timestampExpression1, timestampExpression2 ) To perform TIMESTAMPDIFF on dates and times, it is necessary to convert the dates and times to timestamps. Dates are converted to timestamps by putting 00:00:00.0 in the time-of-day fields. Times are converted to timestamps by putting the current date in the date fields. You should not put a datetime column inside of a timestamp arithmetic function in WHERE clauses because the optimizer will not use any index on the column. Valid intervals for TIMESTAMPADD and TIMESTAMPDIFF The TIMESTAMPADD and TIMESTAMPDIFF functions are used to perform arithmetic with timestamps. These two functions use the following valid intervals for arithmetic operations: • SQL_TSI_DAY • SQL_TSI_FRAC_SECOND • SQL_TSI_HOUR • SQL_TSI_MINUTE • SQL_TSI_MONTH • SQL_TSI_QUARTER • SQL_TSI_SECOND • SQL_TSI_WEEK • SQL_TSI_YEAR Examples for the TIMESTAMPADD and TIMESTAMPDIFF escape functions To return a timestamp value one month later than the current timestamp, use the following syntax: {fn TIMESTAMPADD( SQL_TSI_MONTH, 1, CURRENT_TIMESTAMP)} To return the number of weeks between now and the specified time on January 1, 2008, use the following syntax: {fn TIMESTAMPDIFF(SQL_TSI_WEEK, CURRENT_TIMESTAMP, timestamp('2008-01-01-12.00.00.000000'))} JDBC Escape Syntax for Outer Joins SQLFire interprets the JDBC escape syntax for outer joins (and all join operations) as equivalent to the correct SQL syntax for outer joins or the appropriate join operation. See also Query Capabilities and Limitations on page 768. 376 vFabric SQLFire User's Guide JDBC API Syntax {oj JOIN Operations on page 565 [ JOIN Operations on page 565 ]* } Equivalent to JOIN Operations on page 565 [ JOIN Operations on page 565 ]* -- outer join SELECT * FROM {oj Countries LEFT OUTER JOIN Cities ON (Countries.country_ISO_code=Cities.country_ISO_code)} -- another join operation SELECT * FROM {oj Countries JOIN Cities ON (Countries.country_ISO_code=Cities.country_ISO_code)} -- a TableExpression can be a joinOperation. Therefore -- you can have multiple join operations in a FROM clause SELECT E.EMPNO, E.LASTNAME, M.EMPNO, M.LASTNAME FROM {oj EMPLOYEE E INNER JOIN DEPARTMENT INNER JOIN EMPLOYEE M ON MGRNO = M.EMPNO ON E.WORKDEPT = DEPTNO}; JDBC Escape Syntax for Time Formats SQLFire interprets the JDBC escape syntax for time as equivalent to the correct SQL syntax for times. SQLFire also supports the ISO format of 8 characters (6 digits, and 2 decimal points). 377 vFabric SQLFire Reference Syntax {t 'hh:mm:ss'} Equivalent to TIME 'hh:mm:ss' Example VALUES {t '20:00:03'} JDBC Escape Syntax for Date Formats SQLFire interprets the JDBC escape syntax for dates as equivalent to the correct SQL syntax for dates. Syntax {d 'yyyy-mm-dd'} Equivalent to DATE 'yyyy-mm-dd' Example VALUES {d '1995-12-19'} JDBC Escape Syntax for Timestamp Formats SQLFire interprets the JDBC escape syntax for timestamp as equivalent to the correct SQL syntax for timestamps. SQLFire also supports the ISO format of 23 characters (17 digits, 3 dashes, and 3 decimal points). Syntax {ts 'yyyy-mm-dd hh:mm:ss.f...'} Equivalent to TIMESTAMP 'yyyy-mm-dd hh:mm:ss.f...' The fractional portion of timestamp constants (.f...) can be omitted. VALUES {ts '1999-01-09 20:11:11.123455'} 378 vFabric SQLFire User's Guide Chapter 53 sqlf Launcher Commands Use the sqlf command-line utility to launch SQLFire utilities. • Syntax on page 379 • Description on page 380 Syntax To display a full list of sqlf commands and options: sqlf --help The command form to display a particular utility's usage is: sqlf --help With no arguments, sqlf starts an sqlf Interactive Commands: sqlf To specify a system property for an interactive sqlf session, you must define the JAVA_ARGS environment variable before starting sqlf. For example, sqlf uses the sqlf.history system property to define the file that stores a list of the commands that are executed during an interactive session. To change this property, you would define it as part of the JAVA_ARGS variable: $ export JAVA_ARGS="-Dsqlf.history=/Users/yozie/sqlf-history.sql" $ sqlf To launch and exit a sqlf utility (rather than start an interactive sqlf shell) use the syntax: sqlf In this command form, is one of the following. Utility name server locator agent version Description Starts and stops a SQLFire Server member, and provides status of a running one. Starts and stops a SQLFire Locator member, and provides status of a running one. Starts and stops a GemFire JMX Agent, and provides status of a running one. Prints SQLFire product version information. 379 vFabric SQLFire Reference Utility name stats Description Prints statistic values from a statistic archive. merge-logs license Merges multiple logs files into a single log. Prints any current SQLFire licenses and information needed to obtain a new license. encrypt-password validate-disk-store version compact-disk-store compact-all-disk-stores revoke-missing-disk-store list-missing-disk-stores shut-down-all backup Encrypts a password for use in the sqlfire.properties file when using BUILTIN authentication, or for use with external data sources using an AsyncEventListener implementation or DBSynchronizer. Confirms whether files of a disk store are valid. Displays SQLFire product version information. Compacts an offline disk store to remove all unneeded records from the persistent files. Asks all the distributed system members to compact their disk stores. Asks the distributed system members to stop waiting for the specified disk store. Prints disk stores that are currently missing from the distributed system. Asks all data store and accessor system members to shut down. Asks all the distributed system members to back up their persistent data. To specify a system property when launching a sqlf utility, use -J-Dproperty_name=property_value argument. Description In addition to launching various utilities provided with SQLFire, when launched without any arguments, sqlf starts an interactive command shell that you can use to connect to a SQLFire system and execute various commands, including SQL statements. The launcher honors the current CLASSPATH environment variable and adds it to the CLASSPATH of the utility or command shell being launched. To pass additional arguments to the JVM, set the JAVA_ARGS environment variable when invoking the sqlf script. Note: The JAVA_ARGS environment variable does not apply to the sqlf server, sqlf locator, and sqlf agent tools that launch a separate background process. To pass Java properties to those tools, use the -J option as described in the help for those tools. The launcher uses the java executable that is found in the PATH. To override this behavior, set the SQLF_JAVA environment variable to point to the desired Java executable. (note the supported JRE versions in Supported Configurations and System Requirements on page 3). 380 vFabric SQLFire User's Guide sqlf Launcher Commands sqlf backup Creates a backup of disk stores for all members running in the distributed system. Each member with persistent data creates a backup of its own configuration and disk stores. • Syntax on page 381 • Description on page 381 • Prerequisites and Best Practices on page 382 • Specifying the Backup Directory on page 382 • Example on page 382 • Output Messages from sqlf backup on page 382 • Backup Directory Structure and Its Contents on page 383 • Restoring an Online Backup on page 423 Syntax Use the mcast-port and -mcast-address, or the -locators options, on the command line to connect to the SQLFire cluster. sqlf backup [-mcast-port=] [-mcast-address=
] [-locators=] [-bind-address=
] [-=]* Alternatively, you can specify these and other distributed system properties in a sqlfire.properties file that is available in the directory where you run the sqlf command. The table describes options for sqlf backup. Option Description Directory in which SQLFire stores the backup content. See Specifying the Backup Directory on page 382. -mcast-port Multicast port used to communicate with other members of the distributed system. If zero, multicast is not used for member discovery (specify -locators instead). Valid values are in the range 0–65535, with a default value of 10334. -mcast-address Multicast address used to discover other members of the distributed system. This value is used only if the -locators option is not specified. The default multicast address is 239.192.81.1. -locators List of locators used to discover members of the distributed system. Supply all locators as comma-separated host:port values. -bind-address The address to which this peer binds for receiving peer-to-peer messages. By default sqlf uses the hostname, or localhost if the hostname points to a local loopback address. -prop-name Any other SQLFire distributed system property. Description An online backup saves the following: 381 vFabric SQLFire Reference • For each member with persistent data, the backup includes disk store files for all stores containing persistent table data. • Configuration files from the member startup. • sqlfire.properties, with the properties the member was started with. • A restore script, written for the member's operating system, that copies the files back to their original locations. For example, in Windows, the file is restore.bat and in Linux, it is restore.sh. Prerequisites and Best Practices • Run this command during a period of low activity in your system. The backup does not block system activities, but it uses file system resources on all hosts in your distributed system and can affect performance. • Do not try to create backup files from a running system using file copy commands. You will get incomplete and unusable copies. • Make sure the backup directory directory exists and has the proper permissions for your members to write to it and create subdirectories. • You might want to compact your disk store before running the backup. See the sqlf compact-all-disk-stores command in Online Compaction. • Make sure that those SQLFire members that host persistent data are running in the distributed system. Offline members cannot back up their disk stores. (A complete backup can still be performed if all table data is available in the running members.) Specifying the Backup Directory The directory you specify for backup can be used multiple times. Each backup first creates a top level directory for the backup, under the directory you specify, identified to the minute. You can use one of two formats: • Use a single physical location, such as a network file server. (For example, /export/fileServerDirectory/sqlfBackupLocation). • Use a directory that is local to all host machines in the system. (For example, ./sqlfBackupLocation). Example Using a backup directory that is local to all host machines in the system: sqlf backup ./sqlfBackupLocation Output Messages from sqlf backup When you run sqlf backup, it reports on the outcome of the operation. If any members were offline when you run sqlf backup, you get this message: The backup may be incomplete. The following disk stores are not online: DiskStore at hostc.vmware.com /home/dsmith/dir3 A complete backup can still be performed if all table data is available in the running members. The tool reports on the success of the operation. If the operation is successful, you see a message like this: Connecting to distributed system: locators=warsaw.vmware.com26340 The following disk stores were backed up: DiskStore at hosta.vmware.com /home/dsmith/dir1 382 vFabric SQLFire User's Guide sqlf Launcher Commands DiskStore at hostb.vmware.com /home/dsmith/dir2 Backup successful. If the operation does not succeed at backing up all known members, you see a message like this: Connecting to distributed system: locators=warsaw.vmware.com26357 The following disk stores were backed up: DiskStore at hosta.vmware.com /home/dsmith/dir1 DiskStore at hostb.vmware.com /home/dsmith/dir2 The backup may be incomplete. The following disk stores are not online: DiskStore at hostc.vmware.com /home/dsmith/dir3 A member that fails to complete its backup is noted in this ending status message and leaves the file INCOMPLETE_BACKUP in its highest level backup directory. Backup Directory Structure and Its Contents Below is the structure of files and directories backed up in a distributed system: 2011-05-02-18-10 /: pc15_8933_v10_10761_54522 2011-05-02-18-10/pc15_8933_v10_10761_54522: config diskstores README.txt restore.sh 2011-05-02-18-10/pc15_8933_v10_10761_54522/config: sqlfire.properties 2011-05-02-18-10/pc15_8933_v10_10761_54522/diskstores: SQLF_DD_DISKSTORE 2011-05-02-18-10/pc15_8933_v10_10761_54522/diskstores/SQLF_DD_DISKSTORE: dir0 2011-05-02-18-10/pc15_8933_v10_10761_54522/diskstores/SQLF_DD_DISKSTORE/dir0: BACKUPSQLF-DD-DISKSTORE_1.crf BACKUPSQLF-DD-DISKSTORE_1.drf BACKUPSQLF-DD-DISKSTORE_2.crf BACKUPSQLF-DD-DISKSTORE_2.drf BACKUPSQLF-DD-DISKSTORE.if Restoring an Online Backup The restore script (restore.sh or restore.bat) copies files back to their original locations. You can do this manually if you wish: 1. Restore your disk stores when your members are offline and the system is down. 2. Read the restore scripts to see where they will place the files and make sure the destination locations are ready. The restore scripts refuse to copy over files with the same names. 3. Run the restore scripts. Run each script on the host where the backup originated. The restore copies these back to their original location. sqlf compact-all-disk-stores Perform online compaction of SQLFire disk stores. Syntax sqlf compact_all_disk_stores [-mcast-port=] [-mcast-address=
] [-locators=] [-bind-address=
] [-=]* 383 vFabric SQLFire Reference The table describes options for sqlf compact_all_disk_stores. If no multicast or locator options are specified on the command-line, then the command uses the sqlfire.properties file (if available) to determine the distributed system to which it should connect. Option -mcast-port Description Multicast port used to communicate with other members of the distributed system. If zero, multicast is not used for member discovery (specify -locators instead). Valid values are in the range 0–65535, with a default value of 10334. -mcast-address Multicast address used to discover other members of the distributed system. This value is used only if the -locators option is not specified. The default multicast address is 239.192.81.1. -locators -bind-address List of locators used to discover members of the distributed system. Supply all locators as comma-separated host:port values. The address to which this peer binds for receiving peer-to-peer messages. By default sqlf uses the hostname, or localhost if the hostname points to a local loopback address. -= Any other SQLFire distributed system property. Description When a CRUD operation is performed on a persistent/overflow table, the data is written to the log files. Any pre-existing operation record for the same row becomes obsolete, and SQLFire marks it as garbage. It compacts an old operation log by copying all non-garbage records into the current log and discarding the old files. Manual compaction can be done for online and offline disk stores. For the online disk store, the current operation log is not available for compaction, no matter how much garbage it contains. Offline compaction runs essentially in the same way, but without the incoming CRUD operations. Also, because there is no current open log, the compaction creates a new one to get started. Online Compaction To run manual online compaction, allow-force-compaction should be true. You can run manual online compaction at any time while the system is running. Oplogs eligible for compaction based on the compaction-threshold are compacted into the current oplog. sqlf compact-disk-store Perform offline compaction of a single SQLFire disk store. Syntax sqlf compact-disk-store + [-maxOplogSize=] 384 vFabric SQLFire User's Guide sqlf Launcher Commands Description When a CRUD operation is performed on a persistent/overflow table the data is written to the log files. Any pre-existing operation record for the same row becomes obsolete, and SQLFire marks it as garbage. It compacts an old operation log by copying all non-garbage records into the current log and discarding the old files. Manual compaction can be done for online and offline disk stores. For the online disk store, the current operation log is not available for compaction, no matter how much garbage it contains. Offline compaction runs essentially in the same way, but without the incoming CRUD operations. Also, because there is no current open log, the compaction creates a new one to get started. Note: You must provide all of the directories in the disk store. If no oplog max size is specified, SQLFire uses the system default. Offline compaction can consume a large amount of memory. If you get a java.lang.OutOfMemory error while running this command, you made need to increase the heap size by setting the -Xmx and -Xms options in the JAVA_ARGS environment variable. sqlf Launcher Commands on page 379 provides more information about setting Java options. Example sqlf compact-disk-store myDiskStoreName /firstDir /secondDir maxOplogSize=maxMegabytesForOplog The output of this command is similar to: Offline compaction removed 12 records. Total number of region entries in this disk store is: 7 sqlf encrypt-password Generates an encrypted password string for use in the sqlfire.properties file when configuring BUILTIN authentication, or when accessing an external data source with an AsyncEventListener implementation or DBsynchronizer configuration. Syntax sqlf encrypt-password [external] [-transformation=] [-keysize=] [-J-D=] [-mcast-port=] [-mcast-address=
] [-locators=] [-bind-address=] [-=]* The command prompts for a password and then displays the encrypted password (using options, if specified) on the console. If a console is not available, an exception is thrown. If the external option is included, the encrypted password is stored in the data dictionary for external use with DBSynchronizer or an AsyncEventListener implementation. 385 vFabric SQLFire Reference Option Description external Include the external option to encrypt and store a password within the SQLFire distributed system, for use with external resources accessed by DBSynchronizer or a custom AsynchEventListener implementation. See Configuring DBSynchronizer on page 211 or Implementing an AsyncEventListener on page 204 for more information. When you specify this option, you must supply additional options to connect to a running SQLFire distributed system (either the -locators option or -mcast-port and -mcast-address). The distributed system generates a private key in the data dictionary to encrypt the password. You can use the AsyncEventHelper.decryptPassword method to decrypt the password in your AsyncEventListener implementation, in order to authenticate with an external data source. This option can also be used in conjunction with the -transformation and -keysize options, described below. Note: Each SQLFire distributed system generates its own private key, and the encrypted value is specific to a particular distributed system. The key is regenerated if, for example, the data dictionary becomes corrrupted and a new data dictionary is created. In this case, you would need to generate new encrypted passwords using sqlf encrypt-password. -transformation This option is only used in combination with the -external option. The transformation to use for symmetric key encryption (the encryption algorithm name). SQLF uses an AES encryption key factory by default. The following algorithm names are supported: • AES • ARCFOUR • DES • DESede • PBKDF2WithHmacSHA1 • PBEWithAnd • PBEWithAnd The last two algorithms define a factory to use for PKCS5 encryption. Specify an encryption algorithm name as well as a digest or PseudoRandom Function (PRF) to configure the factory (for example, PBEWithMD5AndDES). See the Java Cryptography Architecture Sun Providers Documentation for more information about these algorithms. -keysize 386 This option is only used in combination with the -external option. The key size to use for the encryption key. The default is 128 bits. vFabric SQLFire User's Guide sqlf Launcher Commands Option Description -mcast-port Multicast port used to communicate with other members of the distributed system. If zero, multicast is not used for member discovery (specify -locators instead). Valid values are in the range 0–65535, with a default value of 10334. -mcast-address Multicast address used to discover other members of the distributed system. This value is used only if the -locators option is not specified. The default multicast address is 239.192.81.1. -locators List of locators used to discover members of the distributed system. Supply all locators as comma-separated host:port values. -bind-address The address to which this peer binds for receiving peer-to-peer messages. By default sqlf uses the hostname, or localhost if the hostname points to a local loopback address. -= Any other SQLFire distributed system property. Description When used without the external option, sqlf prompts for a password to encrypt, and then displays the encrypted password to the console. Example sqlf encrypt-password Enter User Name: test_user Enter password: test_encryption (not echoed to screen) Re-enter password: test_encryption (not echoed to screen) Encrypted to v23b60032c17ab973929e43d60acc597887a5f3d5658bd You can then add the encrypted password to the specified BUILTIN user account in the sqlfire.properties file, as described in Creating Users for BUILTIN Authentication on page 251. sqlf install-jar Installs a JAR file and automatically loads the JAR file classes into the SQLFire class loader. This makes the JAR classes available to all members of the distributed system (including members that join the system at a later time). Syntax To install a local JAR file to SQLFire, use the syntax: sqlf install-jar -file= -name= [-auth-provider=] [-bind-address=
] [-client-bind-address=
] [-client-port=] [-extra-conn-props=] [-help] [-locators=] [-mcast-address=
] 387 vFabric SQLFire Reference [-mcast-port=] [-password[=]] [-user=] This table describes options for the sqlf install-jar command. Default values are used if you do not specify an option. Option -file Description The local path of the JAR file to install, or a URL that links to the JAR file. This argument is required. -name A unique identifier for the JAR installation. The identifier you provide must specify a schema name delimiter. For example: APP.myjar. This argument is required. -auth-provider Sets the authentication provider to use for peer-to-peer connections as well as client-server connections. Valid values are BUILTIN and LDAP. All other members of the SQLFire distributed system must use the same authentication provider and user definitions. If you omit this option, the connection uses no authentication mechanism. See Configuring Authentication and Authorization on page 249. -bind-address The address to which this peer binds for receiving peer-to-peer messages. By default sqlf uses the hostname, or localhost if the hostname points to a local loopback address. -client-bind-address The hostname or IP address on which a SQLFire locator listens for client connections. The default is "localhost." Use this option with -client-port to attach to a SQLFire cluster as a thin client and perform the command. -client-port The port on which a SQLFire locator listens for client connections. The default is 1527. Use this option with -client-bind-address to attach to a SQLFire cluster as a thin client and perform the command. -extra-conn-props -help, --help -locators A semicolon-separated list of properties to use when connecting to the SQLFire distributed system. Display the help message for this sqlf command. The list of locators as comma-separated host[port] values, used to discover other members of the distributed system. Using -locators creates a peer client member to execute the sqlf command. -mcast-address The multicast address used to discover other members of the distributed system. This value is used only when the -locators option is not specified. The default multicast address is 239.192.81.1. 388 vFabric SQLFire User's Guide sqlf Launcher Commands Option Description Use this option with -mcast-port to attach to a SQLFire cluster as a peer client and perform the command. -mcast-port The multicast port used to communicate with other members of the distributed system. If zero, multicast is not used for member discovery (specify -locators instead). This value is used only if the -locators option is not specified. Valid values are in the range 0–65535, with a default value of 10334. Use this option with -mcast-address to attach to a SQLFire cluster as a peer client and perform the command. -password If the servers or locators have been configured to use authentication, this option specifies the password for the user (specified with the -user option) to use for booting the server and joining the distributed system. The password value is optional. If you omit the password, sqlf prompts you to enter a password from the console. -user If the servers or locators have been configured to use authentication, this option specifies the user name to use for booting the server and joining the distributed system. Description Specify one of these pairs of options with the command to connect to a SQLFire Distributed system and install a JAR file: • Use both -client-bind-address and -client-port to connect to a SQLFire cluster as a thin client and perform the command. • Use both mcast-port and -mcast-address, or use the -locators property to connect to a SQLFire cluster as a peer client and perform the command. The -name that you provide for the JAR must be a unique identifier. You must include a schema name to qualify the identifier. You can use the identifier with later calls to sqlf replace-jar or sqlf remove-jar. The -file option specifies the location of the JAR file to install using either a local path or a URL. After installing the JAR to the distributed system, SQLFire automatically loads the JAR file classes into its class loader; you do not need to explicitly load classes after installing the JAR. The JAR and its classes are available to all members of the SQLFire distributed system, including those that later join the cluster. Note: After you install a JAR file, you cannot modify any of the individual classes or resources within the JAR file. Instead, you must replace the entire JAR file to update a class. See Storing and Loading JAR Files in SQLFire on page 131. Examples This command connects to a SQLFire network server running on localhost:1527, and installs a JAR file named tours.jar to the APP schema: sqlf install-jar -name=APP.toursjar -file=c:\tours.jar 389 vFabric SQLFire Reference This command connects to a SQLFire network server running on myserver:1234 to install the JAR file: sqlf install-jar -name=APP.toursjar -file=c:\tours.jar -client-bind-address=myserver -client-port=1234 This command connects as a peer client to a SQLFire system running on multicast port 1234, and installs the JAR file: sqlf install-jar -name=APP.toursjar -file=c:\tours.jar -mcast-port=1234 -extra-conn-props=host-data=false sqlf list-missing-disk-stores Lists all disk stores with the most recent data for which other members are waiting. Syntax sqlf list-missing-disk-stores [-mcast-port=] [-mcast-address=
] [-locators=] [-bind-address=
] [-=]* If no multicast or locator options are specified on the command-line, the command uses the sqlfire.properties file (if available) to determine the distributed system to which it should connect. The table describes options for sqlf list-missing-disk-stores. Option -mcast-port Description Multicast port used to communicate with other members of the distributed system. If zero, multicast is not used for member discovery (specify -locators instead). Valid values are in the range 0–65535, with a default value of 10334. -mcast-address Multicast address used to discover other members of the distributed system. This value is used only if the -locators option is not specified. The default multicast address is 239.192.81.1. -locators -bind-address -prop-name List of locators used to discover members of the distributed system. Supply all locators as comma-separated host:port values. The address to which this peer binds for receiving peer-to-peer messages. By default sqlf uses the hostname, or localhost if the hostname points to a local loopback address. Any other SQLFire distributed system property. Description Handling Missing Disk Stores on page 102 provides more details about listing and revoking missing disk stores. Example sqlf list-missing-disk-stores -mcast-port=10334 Connecting to distributed system: mcast=/239.192.81.1:10334 390 vFabric SQLFire User's Guide sqlf Launcher Commands 1f811502-f126-4ce4-9839-9549335b734d [curwen.local:/Users/yozie/vmware/sqlf/vFabric_SQLFire_11_bNNNNN/server2/./datadictionary] sqlf locator Allows peers (including other locators) in a distributed system to discover each other without the need to hard-code anything about other peers. Syntax To start a stand-alone locator use the command: sqlf locator start [-J]* [-dir=] [-classpath=] [-distributed-system-id=] [-max-heap=] [-initial-heap=] [-peer-discovery-address= (default is 0.0.0.0)] [-peer-discovery-port= (default 10334)] [-sync= (default false)] [-bind-address=
(default is the -peer-discover-address value)] [-run-netserver= (default true)] [-client-bind-address= (default is bind-address or if not set then loopback)] [-client-port= (default 1527)] [-locators=] [-log-file= (default sqlflocator.log)] [-remote-locators=[,]...] [-auth-provider=] [-server-auth-provider=] [-user=] [-password[=]] [-=]* Note: When starting a locator using sqlf locator start, in addition to using the options listed above you can use any other SQLFire boot properties (-=) on the command-line. The startup script maintains the running status of the locator in a file .sqlflocator.ser. To display the status of a running locator: sqlf locator status [ -dir= ] To stop a running locator: sqlf locator stop [ -dir= ] If you started a locator from a script or batch file using the -sync=false command, you can use the following command to wait until the locator has finished synchronization and finished starting: sqlf locator wait [-J]* [-dir=] The wait command does not return control until the locator has completed startup. The table below describes options for all of the above sqlf locator commands. Default values are used if you do not specify an option. Option -J Description JVM option passed to the spawned SQLFire Locator JVM. For example, use -J-Xmx1024m to set the JVM heap to 1GB. 391 vFabric SQLFire Reference Option -dir -classpath -distributed-system-id Description Working directory of the locator that will contain the SQLFire Locator status file and will be the default location for log file, persistent files, data dictionary, and so forth. This option defaults to the current directory. Location of user classes required by the SQLFire Locator. This path is appended to the current classpath. Integer that uniquely identifies this SQLFire cluster. Set a unique value when using WAN replication between multiple SQLFire clusters. Configure Locators for WAN Member Discovery on page 242 provides more information. -max-heap -initial-heap Set the maximum heap size and initial heap and for the Java VM, using SQLFire default resource manager settings. If you use the -max-heap and -initial-heap options, by default SQLFire sets the critical-heap-percentage to 80% of the heap, and the eviction-heap-percentage to 80% of the critical heap. SQLFire also sets resource management properties for eviction and garbage collection if they are supported by the JVM. -peer-discovery-address -peer-discovery-port -sync Address to which the locator binds for peer discovery (includes servers as well as other locators). Port on which the locator listens for peer discovery (includes servers as well as other locators). Valid values are in the range 1-65535, with a default of 10334. Determines whether the sqlf locator command returns immediately if the locator reaches a "waiting" state. A locator or server reaches the "waiting" state on startup if the member depends on another server or locator to provide up-to-date disk store persistence files. This type of dependency can occur if the locator or server that you are starting was not the last member to shut down in the distributed system, and another member stores the most recent version of persisted data for the system. Specifying -sync=false (the default) causes the sqlf command to return control immediately after the member reaches "waiting" state. With -sync=true (the default for servers), the sqlf command does not return control until after all dependent members have booted and the member has finished synchronizing disk stores. Always use -sync=false (the default) when starting multiple members on the same machine, especially when executing sqlf commands from a shell script or batch file, so that the script file does not hang while waiting for a particular SQLFire member to start. You can use the sqlf locator wait and/or sqlf server wait later in the script to verify that each server has 392 vFabric SQLFire User's Guide sqlf Launcher Commands Option Description finished synchronizing and has reached the "running" state. For example: #!/bin/bash # Start all local SQLFire members to waiting state, regardless of which member holds the most recent # disk store files: sqlf locator start -dir=/locator1 -sync=false sqlf server start -client-port=1528 -locators=localhost[10334] -dir=/server1 -sync=false sqlf server start -client-port=1529 -locators=localhost[10334] -dir=/server2 -sync=false # Wait until all members have finished synchronizing and starting: sqlf locator wait -dir=/locator1 sqlf server wait -dir=/server1 sqlf server wait -dir=/server2 # Continue any additional tasks that require access to the SQLFire members... [...] As an alternative to using sqlf locator wait, you can monitor the current status of SQLFire members using STATUS column in the MEMBERS system table. -bind-address -run-netserver The address to which this peer binds for receiving peer-to-peer messages. By default sqlf uses the -peer-discovery-address value. If true then it starts a network server (see the -client-bind-address and -client-port options to specify where the server should listen) that can service thin clients (defaults to true). If set to false, then the -client-bind-address and -client-port options have no affect. This option defaults to true. -client-bind-address Address to which the network controller binds for client connections. This takes effect only if -run-netserver option is not set to false. -client-port Port that the network controller listens on for client connections, 1-65535 with default of 1527. This takes effect only if -run-netserver option is not set to false. 393 vFabric SQLFire Reference Option -locators Description List of other locators as comma-separated host:port values used as backups in case one of the locators fails. The list must include all other locators in use, and must be configured consistently for every member of the distributed system. Servers must be configured to use all the locators of the distributed system, which includes this locator and all of the others in the list. -remote-locators Comma-separated list of addresses and port numbers of locators for remote SQLFire clusters. Use this option when configuring WAN replication to identify connections to remote SQLFire clusters. Configure Locators for WAN Member Discovery on page 242 provides more information. -auth-provider Sets the authentication mechanism to use for client connections. Valid values are BUILTIN and LDAP. If you omit -server-auth-provider, then this same mechanism is also used for joining the cluster. If you omit both options, then no authentication mechanism is used. See Configuring Authentication and Authorization on page 249. Note that SQLFire enables SQL authorization by default if you specify a client authentication mechanism with -auth-provider. -server-auth-provider The authentication mechanism to use for joining the cluster and talking to other servers and locators in the cluster. Supported values are BUILTIN and LDAP. By default, SQLFire uses the value of -auth-provider if it is specified, otherwise no authentication is used. -user -password If the servers or locators have been configured to use authentication, this option specifies the user name to use for booting the server and joining the distributed system. If the servers or locators have been configured to use authentication, this option specifies the password for the user (specified with the -user option) to use for booting the server and joining the distributed system. The password value is optional. If you omit the password, sqlf prompts you to enter a password from the console. -log-file Path of the file to which this locator writes log messages. The default is sqlflocator.log in the working directory. - Any other SQLFire boot property such as log-level. For example, to start a SQLFire locator as a JMX Manager, use the boot properties described in Using Java Management Extensions (JMX) on page 303. See Configuration Properties on page 327 for a complete list of boot properties. 394 vFabric SQLFire User's Guide sqlf Launcher Commands Description A SQLFire locator allows peers (including other locators) in a distributed system to discover one another without having to hard-code anything about other peers. The other mode of discovery is using multicast that requires the peers to use the same multicast address and port for discovery. A locator can be started on its own, or can be embedded in a server with the full SQLFire engine. Standalone locators are also required for systems that enable network partitioning management. To start embedded locators use the "-start-locator" option to the SQLFire server. Note: Locators are the recommended discovery method for production systems. Additionally, running standalone locators provides the highest reliability and availability for the locator service as a whole. Because a locator has no data or meta-data available, it cannot directly service any of the user table related SQL statements from thin clients. It can only service queries involving inbuilt system tables, and inbuilt system procedure calls. Clients use the connection as a control connection to query the locator for the server with the least amount of load (measured in terms of other active client connections) and transparently create the actual data connection to the server as returned by the locator. The client also keeps track of all the other locators and peers in the distributed system by querying the locator. This practice avoids creating multiple control connections for the same distributed system. If the client detects any two separate user connections referring to locators or servers in the same distributed system then it will use the same control connection for both. The list of all locators and peers is also used for failover if the control connection itself fails. SQLFire locators are necessary for load-balanced client connections, and for full availability of the transparent failover functionality provided by the thin client driver (high-availability, or HA in short). Without locators client connections cannot be load-balanced. Even though clients try to fail over transparently to other servers without locators, this behavior is not as reliable as using locators, and failover may not work transparently if multiple servers fail in quick succession. Always start locator members before starting data stores when you boot a SQLFire distributed system. Converseley, always shut down locators last, after shutting down data store members (preferably with sqlf shut-down-all). Each locator locally persists a copy of the data dictionary required, and may have to wait for other locators to come back online to ensure that it has all the latest updates to the data dictionary. Example Starting a locator generates output such as the following. XXX is the path of current working directory. Starting SQLFire Locator using peer discovery on: 0.0.0.0[10334] Starting network server for SQLFire Locator at address localhost/127.0.0.1[1527] SQLFire Locator pid: 3722 status:running Logs generated in /sqlflocator.log By default sqlf locator start starts the server process locally and uses the current working directory to store logs, locator state and the data dictionary, and uses default TCP port 10334 for peer discovery. A standalone locator does not store any user table data or table meta-data. A sub-directory called datadictionary is created by default in the current working directory of the locator and contains the persistent meta-data of the DDLs required for startup by locator (for example, authentication related privileges) that have been executed in the distributed system from any of the clients or peers. This directory is necessary for a SQLFire locator to startup and function properly. As the output above indicates, a network server is also started by default that binds to localhost on port 1527. This service allows thin clients to connect to one of the servers and execute SQL commands using the DRDA protocol. If you are restarting a locator that was used in a distributed system, the locator may need to wait for another member (server or locator) to join the system in order to synchronize disk store persistence files. In this case, 395 vFabric SQLFire Reference the locator reaches a "waiting" state and does not complete startup until the dependent members join the system. For example: Starting SQLFire Locator using peer discovery on: 0.0.0.0[10334] Starting network server for SQLFire Locator at address localhost/127.0.0.1[1527] Logs generated in /Users/yozie/vmware/sqlf/vFabric_SQLFire_11_b40332/locator1/sqlflocator.log SQLFire Locator pid: 9496 status: waiting Region /_DDL_STMTS_META_REGION has potentially stale data. It is waiting for another member to recover the latest data. My persistent id: DiskStore ID: ff28402d-4fa1-488f-ba47-7bf9dec8248e Name: Location: /10.0.1.31:/Users/yozie/vmware/sqlf/vFabric_SQLFire_11_b40332/locator1/./datadictionary Members with potentially new data: [ DiskStore ID: ea249383-b103-43d5-957b-f9789eadd37c Name: Location: /10.0.1.31:/Users/yozie/vmware/sqlf/vFabric_SQLFire_11_b40332/server2/./datadictionary , DiskStore ID: ff7d62c5-4e03-4c74-975f-c8d3639c1cee Name: Location: /10.0.1.31:/Users/yozie/vmware/sqlf/vFabric_SQLFire_11_b40332/server1/./datadictionary ] Use the "sqlf list-missing-disk-stores" command to see all disk stores that are being waited on by other members. - See log file for details. The locator synchronizes persistent data and completes startup after the dependent members join the system. sqlf Logging Support You can specify JDBC boot properties with sqlf server and sqlf locator commands to configure the log file location and log severity level for SQLFire servers and locators, respectively. Configuring and Using SQLFire Log Files on page 269 provides more information. sqlf merge-logs Merges multiple log files into a single log. Syntax sqlf merge-logs + [-out=] Description The -out option specifies the file in which to write the merged log information. If you do not specify a file, the merged log information is written to stdout. Example sqlf merge-logs sqlfserver-01-00.log sqlfserver-02-00.log sqlfserver-03-00.log -out=merged.log Completed merge of 3 logs to "merged.log". 396 vFabric SQLFire User's Guide sqlf Launcher Commands sqlf remove-jar Removes a JAR file installation, unloaded all classes associated with the JAR. Syntax To remove a JAR file installation and unload the JAR file classes, use the syntax: sqlf remove-jar -name= [-auth-provider=] [-bind-address=
] [-client-bind-address=
] [-client-port=] [-extra-conn-props=] [-help] [-locators=] [-mcast-address=
] [-mcast-port=] [-password[=]] [-user=] This table describes options for the sqlf remove-jar command. Default values are used if you do not specify an option. Option Description -name The unique identifier of the existing JAR installation to remove. The identifier that you provide must specify a schema name delimiter. For example: APP.myjar. This argument is required. -auth-provider Sets the authentication provider to use for peer-to-peer connections as well as client-server connections. Valid values are BUILTIN and LDAP. All other members of the SQLFire distributed system must use the same authentication provider and user definitions. If you omit this option, the connection uses no authentication mechanism. See Configuring Authentication and Authorization on page 249. -bind-address The address to which this peer binds for receiving peer-to-peer messages. By default sqlf uses the hostname, or localhost if the hostname points to a local loopback address. -client-bind-address The hostname or IP address on which a SQLFire locator listens for client connections. The default is "localhost." Use this option with -client-port to attach to a SQLFire cluster as a thin client and perform the command. -client-port The port on which a SQLFire locator listens for client connections. The default is 1527. Use this option with -client-bind-address to attach to a SQLFire cluster as a thin client and perform the command. -extra-conn-props -help, --help A semicolon-separated list of properties to use when connecting to the SQLFire distributed system. Display the help message for this sqlf command. 397 vFabric SQLFire Reference Option -locators Description The list of locators as comma-separated host[port] values, used to discover other members of the distributed system. Using -locators creates a peer client member to execute the sqlf command. -mcast-address The multicast address used to discover other members of the distributed system. This value is used only when the -locators option is not specified. The default multicast address is 239.192.81.1. Use this option with -mcast-port to attach to a SQLFire cluster as a peer client and perform the command. -mcast-port The multicast port used to communicate with other members of the distributed system. If zero, multicast is not used for member discovery (specify -locators instead). This value is used only if the -locators option is not specified. Valid values are in the range 0–65535, with a default value of 10334. Use this option with -mcast-address to attach to a SQLFire cluster as a peer client and perform the command. -password If the servers or locators have been configured to use authentication, this option specifies the password for the user (specified with the -user option) to use for booting the server and joining the distributed system. The password value is optional. If you omit the password, sqlf prompts you to enter a password from the console. -user If the servers or locators have been configured to use authentication, this option specifies the user name to use for booting the server and joining the distributed system. Description Specify one of these pairs of options with the command to connect to a SQLFire Distributed system and remove a JAR file installation: • Use both -client-bind-address and -client-port to connect to a SQLFire cluster as a thin client and perform the command. • Use both mcast-port and -mcast-address, or use the -locators property to connect to a SQLFire cluster as a peer client and perform the command. The -name that you provide for the JAR must be an existing JAR file identifier (created with sqlf install-jar). You must include a schema name to qualify the identifier. SQLF removes the JAR file installation (and the unique identifier) and unloads the JAR file classes. See Storing and Loading JAR Files in SQLFire on page 131. 398 vFabric SQLFire User's Guide sqlf Launcher Commands Examples This command connects to a SQLFire network server running on localhost:1527, and removes the JAR installation name APP.toursjar : sqlf remove-jar -name=APP.toursjar This command connects to a SQLFire network server running on myserver:1234 to remove the JAR file installation: sqlf remove-jar -name=APP.toursjar -client-bind-address=myserver -client-port=1234 This command connects as a peer client to a SQLFire system running on multicast port 1234, and removes the JAR file installation: sqlf remove-jar -name=APP.toursjar -mcast-port=1234 -extra-conn-props=host-data=false sqlf replace-jar Replaces an installed JAR file with the contents of a new JAR file. The classes in the new JAR file are automatically loaded into the SQLFire class loader and they replace any classes that were previously installed for the same JAR identifier. SQLFire also recompiles objects that depend on the JAR file, such as installed listener implementations. Syntax To replace an installed JAR file with the contents of a new JAR file, use the syntax: sqlf replace-jar -file= -name= [-auth-provider=] [-bind-address=
] [-client-bind-address=
] [-client-port=] [-extra-conn-props=] [-help] [-locators=] [-mcast-address=
] [-mcast-port=] [-password[=]] [-user=] This table describes options for the sqlf replace-jar command. Default values are used if you do not specify an option. Option -file Description The local path of the new JAR file, or a URL that links to the JAR file. This argument is required. -name The unique identifier of an existing JAR installation to replace. The identifier you provide must specify a schema name delimiter. For example: APP.myjar. This argument is required. -auth-provider Sets the authentication provider to use for peer-to-peer connections as well as client-server connections. Valid values are BUILTIN and 399 vFabric SQLFire Reference Option Description LDAP. All other members of the SQLFire distributed system must use the same authentication provider and user definitions. If you omit this option, the connection uses no authentication mechanism. See Configuring Authentication and Authorization on page 249. -bind-address -client-bind-address The address to which this peer binds for receiving peer-to-peer messages. By default sqlf uses the hostname, or localhost if the hostname points to a local loopback address. The hostname or IP address on which a SQLFire locator listens for client connections. The default is "localhost." Use this option with -client-port to attach to a SQLFire cluster as a thin client and perform the command. -client-port The port on which a SQLFire locator listens for client connections. The default is 1527. Use this option with -client-bind-address to attach to a SQLFire cluster as a thin client and perform the command. -extra-conn-props -help, --help -locators A semicolon-separated list of properties to use when connecting to the SQLFire distributed system. Display the help message for this sqlf command. The list of locators as comma-separated host[port] values, used to discover other members of the distributed system. Using -locators creates a peer client member to execute the sqlf command. -mcast-address The multicast address used to discover other members of the distributed system. This value is used only when the -locators option is not specified. The default multicast address is 239.192.81.1. Use this option with -mcast-port to attach to a SQLFire cluster as a peer client and perform the command. -mcast-port The multicast port used to communicate with other members of the distributed system. If zero, multicast is not used for member discovery (specify -locators instead). This value is used only if the -locators option is not specified. Valid values are in the range 0–65535, with a default value of 10334. Use this option with -mcast-address to attach to a SQLFire cluster as a peer client and perform the command. -password 400 If the servers or locators have been configured to use authentication, this option specifies the password for the user (specified with the -user option) to use for booting the server and joining the distributed system. vFabric SQLFire User's Guide sqlf Launcher Commands Option Description The password value is optional. If you omit the password, sqlf prompts you to enter a password from the console. -user If the servers or locators have been configured to use authentication, this option specifies the user name to use for booting the server and joining the distributed system. Description Specify one of these pairs of options with the command to connect to a SQLFire Distributed system and replace a JAR file installation: • Use both -client-bind-address and -client-port to connect to a SQLFire cluster as a thin client and perform the command. • Use both mcast-port and -mcast-address, or use the -locators property to connect to a SQLFire cluster as a peer client and perform the command. The -name that you provide for the JAR must be an existing JAR file identifier (created with sqlf install-jar). You must include a schema name to qualify the identifier. The -file option specifies the location of the new JAR file to use for replacing the existing JAR installation. Include either a local path to the file or a URL. See Storing and Loading JAR Files in SQLFire on page 131. Examples This command connects to a SQLFire network server running on localhost:1527, and replaces the JAR installation name APP.toursjar with a new JAR file named tours2.jar: sqlf replace-jar -name=APP.toursjar -file=c:\tours2.jar This command connects to a SQLFire network server running on myserver:1234 to replace the JAR file: sqlf replace-jar -name=APP.toursjar -file=c:\tours2.jar -client-bind-address=myserver -client-port=1234 This command connects as a peer client to a SQLFire system running on multicast port 1234, and replaces the JAR file: sqlf replace-jar -name=APP.toursjar -file=c:\tours2.jar -mcast-port=1234 -extra-conn-props=host-data=false sqlf revoke-missing-disk-store Instruct SQLFire members to stop waiting for a disk store to become available. Syntax sqlf revoke-missing-disk-store [-mcast-port=] [-mcast-address=
] [-locators=] 401 vFabric SQLFire Reference [-bind-address=
] [-=]* The table describes options and arguments for sqlf revoke-missing-disk-store. If no multicast or locator options are specified on the command-line, the command uses the sqlfire.properties file (if available) to determine the distributed system to which it should connect. Option Description (Required.) Specifies the unique ID of the disk store to revoke. You can obtain the ID from the output of sqlf show-disk-store-metadata -mcast-port Multicast port used to communicate with other members of the distributed system. If zero, multicast is not used for member discovery (specify -locators instead). Valid values are in the range 0–65535, with a default value of 10334. -mcast-address Multicast address used to discover other members of the distributed system. This value is used only if the -locators option is not specified. The default multicast address is 239.192.81.1. -locators -bind-address -prop-name List of locators used to discover members of the distributed system. Supply all locators as comma-separated host:port values. The address to which this peer binds for receiving peer-to-peer messages. By default sqlf uses the hostname, or localhost if the hostname points to a local loopback address. Any other SQLFire distributed system property. Description Handling Missing Disk Stores on page 102 provides more details about listing and revoking missing disk stores. Example This command first lists the missing disk store: sqlf list-missing-disk-stores -mcast-port=10334 Connecting to distributed system: mcast=/239.192.81.1:10334 1f811502-f126-4ce4-9839-9549335b734d [curwen.local:/Users/yozie/vmware/sqlf/vFabric_SQLFire_11_bNNNNN/server2/./datadictionary] Next, sqlf revokes the missing disk store if more recent data is available: sqlf revoke-missing-disk-store 1f811502-f126-4ce4-9839-9549335b734d -mcast-port=10334 Connecting to distributed system: mcast=/239.192.81.1:10334 revocation was successful and no disk stores are now missing Finally, sqlf verifies that no disk stores are missing: sqlf list-missing-disk-stores -mcast-port=10334 Connecting to distributed system: mcast=/239.192.81.1:10334 The distributed system did not have any missing disk stores 402 vFabric SQLFire User's Guide sqlf Launcher Commands sqlf run Connects to a SQLFire distributed system and executes the contents of a SQL command file. All commands in the specified file must be compatible with the interactive sqlf shell. Syntax sqlf run -file= [-auth-provider=] [-bind-address=
] [-client-bind-address=
] [-client-port=] [-encoding=] [-extra-conn-props=] [-help] [-ignore-errors] [-J-D] [-locators=] [-mcast-address=
] [-mcast-port=] [-password[=]] [-path=] [-user=] This table describes options for the sqlf run command. Default values are used if you do not specify an option. Option -file Description The local path of a SQL command file to execute, or a URL that links to the SQL command file. All commands in the specified file must be compatible with the interactive sqlf shell. This argument is required. -auth-provider Sets the authentication provider to use for peer-to-peer connections as well as client-server connections. Valid values are BUILTIN and LDAP. All other members of the SQLFire distributed system must use the same authentication provider and user definitions. If you omit this option, the connection uses no authentication mechanism. See Configuring Authentication and Authorization on page 249. -bind-address The address to which this peer binds for receiving peer-to-peer messages. By default sqlf uses the hostname, or localhost if the hostname points to a local loopback address. -client-bind-address The hostname or IP address on which a SQLFire locator listens for client connections. The default is "localhost." Use this option with -client-port to attach to a SQLFire cluster as a thin client and perform the command. -client-port The port on which a SQLFire locator listens for client connections. The default is 1527. Use this option with -client-bind-address to attach to a SQLFire cluster as a thin client and perform the command. 403 vFabric SQLFire Reference Option Description -encoding The character set encoding of the SQL script file (-file argument). The default is UTF-8. Other possible values are: US-ASCII, ISO-8859-1, UTF-8, UTF-16BE, UTF-16LE, UTF-16. See the java.nio.charset.Charset reference for more information. -extra-conn-props -help, --help A semicolon-separated list of properties to use when connecting to the SQLFire distributed system. Display the help message for this sqlf command. -ignore-errors Include this option to ignore any errors that may occur while executing statements in the file, and continue executing the remaining statements. If you omit this option, then sqlf immediately terminates the script's execution if an exception occurs. -J-D Sets Java system property to the specified value. -locators The list of locators as comma-separated host[port] values, used to discover other members of the distributed system. Using -locators creates a peer client member to execute the sqlf command. -mcast-address The multicast address used to discover other members of the distributed system. This value is used only when the -locators option is not specified. The default multicast address is 239.192.81.1. Use this option with -mcast-port to attach to a SQLFire cluster as a peer client and perform the command. -mcast-port The multicast port used to communicate with other members of the distributed system. If zero, multicast is not used for member discovery (specify -locators instead). This value is used only if the -locators option is not specified. Valid values are in the range 0–65535, with a default value of 10334. Use this option with -mcast-address to attach to a SQLFire cluster as a peer client and perform the command. -password If the servers or locators have been configured to use authentication, this option specifies the password for the user (specified with the -user option) to use for booting the server and joining the distributed system. The password value is optional. If you omit the password, sqlf prompts you to enter a password from the console. -path Configures the working directory for any other SQL command files executed from within the script. The -path entry is prepended to any SQL script file name executed that the script executes in a run command. 404 vFabric SQLFire User's Guide sqlf Launcher Commands Option Description -user If the servers or locators have been configured to use authentication, this option specifies the user name to use for booting the server and joining the distributed system. Description Specify one of these pairs of options with the command to connect to a SQLFire Distributed system and execute a SQL command file: • Use both -client-bind-address and -client-port to connect to a SQLFire cluster as a thin client and perform the command. • Use both mcast-port and -mcast-address, or use the -locators property to connect to a SQLFire cluster as a peer client and perform the command. The -file argument specifies the location of the SQL script file to execute. If the script file itself calls other script files using run 'filename', also consider using the -path option to specify the location of the embedded script files. If an exception occurs while executing the script, SQLF immediately stops executing script commands, unless you include the -ignore-errors option. Examples This command connects to a SQLFire network server running on myserver:1234 and executes commands in the ToursDB_schema.sql file: sqlf run -file=c:\sqlfire\quickstart\ToursDB_schema.sql -client-bind-address=myserver -client-port=1234 This command executes the loadTables.sql script, which calls dependent scripts such as loadCOUNTRIES.sql, loadCITIES.sql, and so forth. If you execute this command outside of the directory in which the dependent scripts are located, you must specify the working directory using the -path option. For example: sqlf run -file=c:\sqlfire\quickstart\loadTables.sql -path=c:\sqlfire\quickstart -client-bind-address=myserver -client-port=1234 sqlf server A SQLFire server is the main server side component in a SQLFire system that provides connectivity to other servers, peers, and clients in the cluster. It can host data. A server is started using the server utility of the sqlf launcher. • Syntax on page 405 • Description on page 410 • Example: Multiple Servers Using Default Multicast Port for Peer Discovery on page 412 • Example: Servers and Client Using Locator on page 412 • Example: Multiple Locators for High Availability on page 413 • Example: Servers and Accessors with a Locator on page 414 • Example: Servers and Locator Using BUILTIN Authentication on page 414 • Example: Servers and Accessors with Server Groups and Locator on page 415 405 vFabric SQLFire Reference Syntax To start a SQLFire server : sqlf server start [-J]* [-dir=] [-classpath=] [-max-heap=] [-initial-heap=] [-server-groups=] [-run-netserver= (default true)] [-sync= (default true)] [-rebalance] [-config-scripts=] [-init-scripts=] [-bind-address=
(default is hostname or localhost if hostname points to a local loopback address)] [-client-bind-address= (default is localhost)] [-client-port= (default 1527)] [-critical-heap-percentage= (default 90 if -max-heap and -initial-heap both are provided, otherwise not configured)] [-eviction-heap-percentage= (default 80% of critical-heap-percentage)] [-mcast-port= (default 10334)] [-mcast-address=
(default 239.192.81.1)] [-locators=] [-start-locator=
] [-host-data= (default true)] [-auth-provider=] [-server-auth-provider=] [-user=] [-password[=]] [-log-file= (default sqlfserver.log)] [-=]* To display the status of a running server: sqlf server status [ -dir= ] To stop a running server: sqlf server stop [ -dir= ] If you started a server from a script or batch file using the -sync=false command, you can use the following command to wait until the server has finished synchronization and finished starting: sqlf server wait [-J]* [-dir=] The wait command does not return control until the locator has completed startup. To stop all running accessor and datastore members in the system, use the following command from within a server working directory: sqlf shut-down-all The table describes the options of the sqlf server command. Default values are used if you do not specify an option. 406 Option Description -J JVM option passed to the spawned SQLFire server JVM. For example, use -J-Xmx1024m to set the JVM heap to 1GB. -dir Working directory of the server that will contain the SQLFire Server status file and will be the default location for log file, persistent files, data dictionary, and so forth (defaults to the current directory) . vFabric SQLFire User's Guide sqlf Launcher Commands Option Description -classpath Location of user classes required by the SQLFire Server. This path is appended to the current classpath. -max-heap -initial-heap Set the maximum heap size and initial heap and for the Java VM, using SQLFire default resource manager settings. If you use the -max-heap and -initial-heap options, by default SQLFire sets the critical-heap-percentage to 80% of the heap, and the eviction-heap-percentage to 80% of the critical heap. SQLFire also sets resource management properties for eviction and garbage collection if they are supported by the JVM. -server-groups Comma-separated list of server groups to which this member belongs. Used for creating tables in particular sets of servers or for firing data-aware procedures in particular server groups. See CREATE TABLE on page 505 and CALL on page 488. If this option is not specified then the server only belongs to the default server group. The default server group has no name and contains all members of the distributed system. Note: SQLFire converts the server group names that you specify to use all-uppercase characters. -run-netserver If true, starts a network server that can service thin clients. See the -client-bind-address and -client-port options to specify where the server should listen. Defaults is true. If set to false, the -client-bind-address and -client-port options have no effect. -sync Determines whether the sqlf server command returns immediately if the server reaches a "waiting" state. A locator or server reaches the "waiting" state on startup if the member depends on another server or locator to provide up-to-date disk store persistence files. This type of dependency can occur if the locator or server that you are starting was not the last member to shut down in the distributed system, and another member stores the most recent version of persisted data for the system. Specifying -sync=false (the default) causes the sqlf command to return control immediately after the member reaches "waiting" state. With -sync=true, the sqlf command does not return control until after all dependent members have booted and the member has finished synchronizing disk stores. Always use -sync=false (the default) when starting multiple members on the same machine, especially when executing sqlf commands from a shell script or batch file, so that the script file does not hang while waiting for a particular SQLFire member to start. You can use the sqlf locator wait and/or sqlf server wait later in the script to verify that each server has 407 vFabric SQLFire Reference Option Description finished synchronizing and has reached the "running" state. For example: #!/bin/bash # Start all local SQLFire members to waiting state, regardless of which member holds the most recent # disk store files: sqlf locator start -dir=/locator1 -sync=false sqlf server start -client-port=1528 -locators=localhost[10334] -dir=/server1 -sync=false sqlf server start -client-port=1529 -locators=localhost[10334] -dir=/server2 -sync=false # Wait until all members have finished synchronizing and starting: sqlf locator wait -dir=/locator1 sqlf server wait -dir=/server1 sqlf server wait -dir=/server2 # Continue any additional tasks that require access to the SQLFire members... [...] As an alternative to using sqlf server wait, you can monitor the current status of SQLFire members using STATUS column in the MEMBERS system table. -rebalance Causes the new member to trigger a rebalancing operation for all partitioned tables in the system. The system always tries to satisfy the redundancy of all partitioned tables on new member startup regardless of this option. -config-scripts Comma-separated list of files containing initial SQL commands to be executed by this member prior to executing any other commands. The format of these files is same as that required by the SQLFire command shell. The scripts in "-config-scripts" should include configuration and other options, or initial DDL statements to be executed before any other operation in the member, including execution of initial DDLs from other members or those persisted in the default disk store of this member. -init-scripts 408 As with config-scripts, this is a comma-separated list of files containing the initial SQL commands to be executed in the same format as that required by the SQLFire command shell. Unlike config-scripts, these commands are executed after completing the initial DDL replay from persisted data in this member or from existing vFabric SQLFire User's Guide sqlf Launcher Commands Option Description members. This brings the meta-data to consistent state with the cluster before executing the script. In the script file, you can include commands that require the existence of tables and other objects. For example, you might include DML statements that to load initial data into existing tables. -client-address The address to which this peer binds for receiving peer-to-peer messages. By default sqlf uses the hostname, or localhost if the hostname points to a local loopback address. -client-bind-address Address to which the network controller binds for client connections. This takes effect only if "-run-netserver" option is not set to false. -client-port Port that the network controller listens on for client connections, 1-65535 with default of 1527. This takes effect only if "-run-netserver" option is not set to false. -critical-heap-percentage Sets the Resource Manager's critical heap threshold in percentage of the old generation heap, 0-100. If you set -max-heap and -initial-heap, the default value for critical-heap-percentage is set to 90% of the heap size. Use this switch to override the default. When this limit is breached, the system starts canceling memory-intensive queries, throws low memory exceptions for new SQL statements, and so forth, to avoid running out of memory. -eviction-heap-percentage Sets the memory usage percentage threshold (0-100) that the Resource Manager will use to start evicting data from the heap. By default, the eviction threshold is 80% of whatever is set for -critical-heap-percentage. Use this switch to override the default. -mcast-port Multicast port used to communicate with other members of the distributed system. If zero, multicast is disabled for both member discovery and distribution. Valid values are in the range 0..65535 with default of 10334. This value must be consistent across all the members of cluster. -mcast-address Multicast address used to discover other members of the distributed system. Only used if mcast-port is non-zero. The default multicast address is 239.192.81.1 as assigned by IANA (http://www.iana.org/assignments/multicast-addresses). This must be consistent across all the members of cluster. -locators List of locators as comma-separated host:port values used to communicate with running locators in the system and thus discover other peers of the distributed system. The list must include all locators in use, and must be configured consistently for every member of the distributed system. The default is no locators, so the system uses multicast for peer discovery. Use of locators is recommended for production systems. 409 vFabric SQLFire Reference Option Description -start-locator Specifies an embedded locator in this server that is started and stopped automatically with this server. The locator is specified as
[] (note the square brackets), or just . When address is not specified, the one specified in "-bind-address" is used, if set. Otherwise the machine's default address is used. -host-data If set to false, this peer does not host table data and acts as an accessor member, still having the capability to route queries to appropriate datastores and aggregating the results. -auth-provider Authentication mechanism for client connections. If -server-auth-provider is not specified, then this same mechanism is also used for joining the cluster. Supported values are BUILTIN and LDAP. Note that SQLFire enables SQL authorization by default if you specify a client authentication mechanism with -auth-provider. By default, no authentication is used. -server-auth-provider Authentication mechanism for joining the cluster and talking to other servers and locators in the cluster. Supported values are BUILTIN and LDAP. By default, SQLFire uses the value of -auth-provider if it is specified, otherwise no authentication is used. -user If the servers or locators have been configured to use authentication, this option specifies the user name to use for booting the server and joining the distributed system. -password If the servers or locators are configured for authentication, this option specifies the password for the user (specified with the -user option) to use for booting the server and joining the distributed system. The password value is optional. If you omit the password, sqlf prompts you to enter a password from the console. -log-file Path of the file to which this member writes log messages (default is sqlfserver.log in the working directory) - Any other SQLFire boot property such as "log-level". For example, to start a SQLFire server as a JMX Manager, use the boot properties described in Using Java Management Extensions (JMX) on page 303. See Configuration Properties on page 327 for a complete list of boot properties. Description You can start servers that can host data (data stores) or those that do not host data (accessors) with the sqlf utility, but either kind of member can service all SQL statements by routing them to appropriate data stores and aggregating the results. Even for a member hosting data for a table, it is not necessary that all data be available in the same member, for example, for DMLs that reference partitioned tables (PARTITION BY Clause). So routing to other stores may be required. In addition it is possible for a member to be a data store but still not host any data for a table due to no common SERVER GROUPS Clause. 410 vFabric SQLFire User's Guide sqlf Launcher Commands Starting a server generates output similar to the following (XXX is the path of current working directory): Starting SQLFire Server using multicast for peer discovery: 239.192.81.1[10334] Starting network server for SQLFire Server at address localhost/127.0.0.1[1527] SQLFire Server pid: 2015 status: running Logs generated in /sqlfserver.log This will start the server process locally and use the current working directory to store logs, statistics and the data dictionary, and use multicast for peer discovery (address 239.192.81.1, port 10334). Any persistent tables created using the default disk store will also use this directory to manage the data files. The data dictionary is managed in a subdirectory called 'datadictionary' and persisted by default. This subdirectory contains the persistent metadata of all the DDLs executed in the distributed system from any clients or peers, and is necessary for a SQLFire server or locator member to start up and function properly. As the output above indicates, a network server is also started by default that binds to localhost on port 1527. This service allows thin clients to connect to the server and execute SQL commands using the DRDA protocol. A SQLFire server that you are starting may require other cluster members (locators or servers) to boot before it can confirm that its data is consistent with those members' data. Even with no persistent or overflow tables, each server locally persists a copy of the data dictionary and may remain in a "waiting" state until dependent locators or server come back online to ensure that it has all the latest updates to the data dictionary: Starting SQLFire Server using locators for peer discovery: localhost[10334] Starting network server for SQLFire Server at address localhost/127.0.0.1[1528] Logs generated in /Users/yozie/vmware/sqlf/vFabric_SQLFire_11_b40332/server1/sqlfserver.log SQLFire Server pid: 9502 status: waiting Region /_DDL_STMTS_META_REGION has potentially stale data. It is waiting for another member to recover the latest data. My persistent id: DiskStore ID: ff7d62c5-4e03-4c74-975f-c8d3639c1cee Name: Location: /10.0.1.31:/Users/yozie/vmware/sqlf/vFabric_SQLFire_11_b40332/server1/./datadictionary Members with potentially new data: [ DiskStore ID: ea249383-b103-43d5-957b-f9789eadd37c Name: Location: /10.0.1.31:/Users/yozie/vmware/sqlf/vFabric_SQLFire_11_b40332/server2/./datadictionary ] Use the "sqlf list-missing-disk-stores" command to see all disk stores that are being waited on by other members. - See log file for details. Use -sync=false when starting SQLFire members in a shell script or batch file to return control to the script immediately after the member reaches the "waiting" state. If another server is now started to join the cluster using the same multicast port (default port as for the first server above), the startup message shows the other members in the distributed system: sqlf server start -dir=server2 -client-port=1528 Starting SQLFire Server using multicast for peer discovery: 239.192.81.1[10334] Starting network server for SQLFire Server at address localhost/127.0.0.1[1528] 411 vFabric SQLFire Reference Distributed system now has 2 members. Other members: serv1(2015:data store):32013/48225 SQLFire Server pid: 2032 status: running Logs generated in /sqlfserver.log The italicized lines indicate the output regarding the IDs of other members in the distributed system. The startup script maintains the running status of the server in a file .sqlfserver.ser. Example: Multiple Servers Using Default Multicast Port for Peer Discovery -- start a server using default mcast-port (10334) for discovery, -- with current directory as the working directory, and network server –- running on default localhost:1527 sqlf server start –- start a second server talking to the first with dir2 as working directory; –- network server is started explicitly on localhost:1528 sqlf server start -dir=dir2 -client-port=1528 –- start another server talking to the first two with dir3 as working –- directory; network server is disabled explicitly sqlf server start -dir=dir3 -run-netserver=false –- check from the SQLFire command shell sqlf sqlf> connect client 'localhost:1527'; sqlf> select ID from sys.members; –- output will show three members in the distributed system –- stop everything sqlf> quit; sqlf server stop -dir=dir3 sqlf server stop -dir=dir2 sqlf server stop Example: Servers and Client Using Locator –- start a locator for peer discovery on port 3241 -- listening on all addresses sqlf locator start -peer-discovery-port=3241 –- start three servers as before using different client ports -- and using the above started locator sqlf server start -dir=dir1 -locators=localhost:3241 -client-port=1528 sqlf server start -dir=dir2 -locators=localhost:3241 -client-port=1529 sqlf server start -dir=dir3 -locators=localhost:3241 -client-port=1530 –- check from the SQLFire command shell –- connect using the locator's client-port (default 1527) -- for load balanced connection to one of the servers -- transparently and for reliable failover in case the -- server goes down sqlf sqlf> connect client 'localhost:1527'; sqlf> select ID, KIND from sys.members; –- output will show four members with three as data stores 412 vFabric SQLFire User's Guide sqlf Launcher Commands -- and one as locator –- stop everything sqlf> quit; sqlf server stop -dir=dir3 sqlf server stop -dir=dir2 sqlf server stop -dir=dir1 sqlf locator stop Example: Multiple Locators for High Availability –- start two locators that configured to talk -- to one another sqlf locator start -peer-discovery-port=3241 -locators=localhost:3242 sqlf locator start -dir=loc2 -peer-discovery-port=3242 -locators=localhost:3241 -client-port=1528 –- start four servers that can talk to both -- the above locators sqlf server start -dir=dir1 -locators=localhost:3241,localhost:3242 -client-port=1529 sqlf server start -dir=dir2 -locators=localhost:3241,localhost:3242 -client-port=1530 sqlf server start -dir=dir3 -locators=localhost:3241,localhost:3242 -client-port=1531 sqlf server start -dir=dir4 -locators=localhost:3241,localhost:3242 -client-port=1532 –- check all the members in the distributed system sqlf sqlf> connect client 'localhost:1527'; sqlf> select ID, KIND from sys.members order by KIND DESC; -– output will show six members with two locators -- followed by four data stores sqlf> quit; –- now bring down the first locator and check that -- new servers can still join sqlf locator stop sqlf server start -dir=dir5 -locators=localhost:3241,localhost:3242 -client-port=1533 –- check all the members in the distributed system again sqlf sqlf> connect client 'localhost:1528'; sqlf> select ID, KIND from sys.members order by KIND DESC; –- output will show six members with one locator -- followed by five data stores –- stop everything sqlf> quit; sqlf server stop -dir=dir5 sqlf server stop -dir=dir4 sqlf server stop -dir=dir3 sqlf server stop -dir=dir2 413 vFabric SQLFire Reference sqlf server stop -dir=dir1 sqlf locator stop -dir=loc2 Example: Servers and Accessors with a Locator –- start a locator for peer discovery on port 3241 sqlf locator start -peer-discovery-port=3241 –- start three servers using different client ports and -- using the above started locator sqlf server start -dir=dir1 -locators=localhost:3241 -client-port=1528 sqlf server start -dir=dir2 -locators=localhost:3241 -client-port=1529 sqlf server start -dir=dir3 -locators=localhost:3241 -client-port=1530 –- start a couple of peers that will not host data sqlf server start -dir=dir4 -locators=localhost:3241 -client-port=1531 -host-data=false sqlf server start -dir=dir5 -locators=localhost:3241 -client-port=1532 -host-data=false –- check from the SQLFire command shell –- connect using the locator's client-port (default 1527) -- for load balanced connection to one of the servers/accessors -- transparently and for reliable failover in case the -- server/accessor goes down sqlf sqlf> connect client 'localhost:1527'; sqlf> select ID, KIND from sys.members; –- output will show six members with one as locator, three -- data stores and two accessors Example: Servers and Locator Using BUILTIN Authentication –- start a locator for peer discovery on port 3241 -- with authentication; below specifies a builtin -- system user on the command-line itself -- (sqlfire.user.gem1=gem1) but it is recommended -- to be in sqlfire.properties in encrypted form -- using the "sqlf encrypt-password" tool sqlf locator start -peer-discovery-port=3241 -auth-provider=BUILTIN -sqlfire.user.gem1=gem1 -user=gem1 -password=gem1 –- start three servers using different client -- ports and using the above started locator sqlf server start -dir=dir1 -locators=localhost:3241 -client-port=1528 -auth-provider=BUILTIN -sqlfire.user.gem1=gem1 -user=gem1 -password=gem1 sqlf server start -dir=dir2 -locators=localhost:3241 -client-port=1529 -auth-provider=BUILTIN -sqlfire.user.gem1=gem1 -user=gem1 -password=gem1 sqlf server start -dir=dir3 -locators=localhost:3241 -client-port=1530 -auth-provider=BUILTIN -sqlfire.user.gem1=gem1 -user=gem1 -password=gem1 –- check from the SQLFire command shell –- connect using the locator's client-port -- (default 1527) for load balanced –- connection to one of the servers/accessors 414 vFabric SQLFire User's Guide sqlf Launcher Commands -- transparently and for reliable -- failover in case the server/accessor goes down sqlf sqlf> connect client 'localhost:1527;user=gem1;password=gem1'; –- add a new database user sqlf> call sys.create_user('sqlfire.user.gem2', 'gem2'); –- check members sqlf> select ID, KIND from sys.members; –- output will show four members with one as -- locator and three data stores Example: Servers and Accessors with Server Groups and Locator –- start a locator for peer discovery on port 3241 sqlf locator start -peer-discovery-port=3241 –----- start three servers using different client ports and using the above started locator using two server groups (ordersdb and customers) with one server in both the groups sqlf server start -client-port=1528 sqlf server start -client-port=1529 sqlf server start -client-port=1530 -dir=dir1 -locators=localhost:3241 -server-groups=ordersdb -dir=dir2 -locators=localhost:3241 -server-groups=customers -dir=dir3 -locators=localhost:3241 -server-groups=ordersdb,customers –- start a couple of peers that will -- not host data but in both server -- groups; using server groups in -- accessors is only useful if -- executing data-aware procedures -- targeted to those members sqlf server start -dir=dir4 -locators=localhost:3241 -client-port=1531 -host-data=false -server-groups=ordersdb,customers sqlf server start -dir=dir5 -locators=localhost:3241 -client-port=1532 -host-data=false -server-groups=ordersdb,customers –- check from the SQLFire command shell –- connect using the locator's client-port -- (default 1527) for load balanced –- connection to one of the servers/accessors -- transparently and for reliable -- failover in case the server/accessor -- goes down sqlf sqlf> connect client 'localhost:1527'; sqlf> select ID, KIND from sys.members; –- example output ID |KIND ----------------------------------------------pc29(23372):28185/36245 |locator(normal) pc29(23742):19653/33509 pc29(23880):37719/51114 |datastore(normal) |accessor(normal) 415 vFabric SQLFire Reference pc29(23611):52031/53106 pc29(24021):58510/43678 |datastore(normal) |accessor(normal) pc29(23503):30307/36105 |datastore(normal) 6 rows selected -- also check for server groups sqlf> select ID, KIND, SERVERGROUPS from sys.members; -- example output ID |KIND |SERVERGROUPS ----------------------------------------------------------------pc29(23372):28185/36245 |locator(normal) | pc29(23742):19653/33509 |datastore(normal) |CUSTOMERS,ORDERSDB pc29(23880):37719/51114 |accessor(normal) |CUSTOMERS,ORDERSDB pc29(23611):52031/53106 |datastore(normal) |CUSTOMERS pc29(24021):58510/43678 |accessor(normal) |CUSTOMERS,ORDERSDB pc29(23503):30307/36105 |datastore(normal) |ORDERSDB 6 rows selected sqlf show-disk-store-metadata Display the disk store metadata for a specified disk store directory. Syntax sqlf show-disk-store-metadata + [-mcast-port=] [-mcast-address=
] [-locators=] [-bind-address=
] [-=]* The table describes options and arguments for sqlf show-disk-store-metadata. If no multicast or locator options are specified on the command-line, the command uses the sqlfire.properties file (if available) to determine the distributed system to which it should connect. Option Description (Required.) Specifies the name of a disk store for which you want to display metadata. The disk store must be offline. (Required.) Specifies one or more disk store file directories. -mcast-port Multicast port used to communicate with other members of the distributed system. If zero, multicast is not used for member discovery (specify -locators instead). Valid values are in the range 0–65535, with a default value of 10334. 416 vFabric SQLFire User's Guide sqlf Launcher Commands Option -mcast-address Description Multicast address used to discover other members of the distributed system. This value is used only if the -locators option is not specified. The default multicast address is 239.192.81.1. -locators -bind-address -prop-name List of locators used to discover members of the distributed system. Supply all locators as comma-separated host:port values. The address to which this peer binds for receiving peer-to-peer messages. By default sqlf uses the hostname, or localhost if the hostname points to a local loopback address. Any other SQLFire distributed system property. Description This command displays metadata information for all available disk stores in the specified directory. On Linux RPM installations, the disk store directory and files are owned by the non-interactive sqlfire user. You must use sudo -u sqlfire to execute the disk store command. Example This command displays metadata for all disk stores in a single directory: sudo -u sqlfire sqlf show-disk-store-metadata SQLF-DEFAULT-DISKSTORE /var/opt/vmware/sqlfire/server Disk Store ID: cb70441cf00f43f7-93b3cc5fe1ecd2d9 Regions in the disk store: /__UUID_PERSIST lru=lru-entry-count lruAction=overflow-to-disk lruLimit=100 concurrencyLevel=16 initialCapacity=16 loadFactor=0.75 statisticsEnabled=false drId=9 isBucket=false clearEntryId=0 MyInitializingID= MyPersistentID= onlineMembers: offlineMembers: equalsMembers: sqlf shut-down-all Instructs all SQLFire accessor and data store members to disconnect from the distributed system and shut down. Syntax sqlf shut-down-all [-bind-address=
] 417 vFabric SQLFire Reference [-locators=] [-mcast-port=] [-mcast-address=
] [-skip-accessors] [-=]* The table shows arguments and options for sqlf shut-down-all. Option Description -bind-address The address to which this peer binds for receiving peer-to-peer messages. By default sqlf uses the hostname, or localhost if the hostname points to a local loopback address. -locators -mcast-address List of locators used to discover members of the distributed system. Supply all locators as comma-separated host:port values. Multicast address used to discover other members of the distributed system. This value is used only if the -locators option is not specified. The default multicast address is 239.192.81.1. -mcast-port Multicast port used to communicate with other members of the distributed system. If zero, multicast is not used for member discovery (specify -locators instead). Valid values are in the range 0–65535, with a default value of 10334. -skip-accessors Include this option to leave SQLFire accessor members (members that were started with host-data=false) running after executing the shut-down-all command. -prop-name Any other SQLFire distributed system property. If no multicast or locator options are specified on the command-line, then the command uses the sqlfire.properties file (if available) to determine the distributed system to which it should connect. Description This command provides an orderly shutdown for all SQLFire data store and accessor members. Locators are left running to ensure an orderly shut down of the system; shut down locators only after data stores have stopped. On the next startup, data store members will still need to wait until the member with the most recent copy of persisted data joins the distributed system. Example This command shuts down data store and accessor members in a system that uses multicast for discovery: sqlf shut-down-all -mcast-port=3000 Connecting to distributed system: mcast=/239.192.81.1:3000 Successfully shut down 2 members sqlf stats Displays statistics values from the statistics archive. • Syntax on page 424 • Restoring an Online Backup on page 423 418 vFabric SQLFire User's Guide sqlf Launcher Commands • Example 1: Starting a Server with Statistics Archiving Enabled on page 424 • Example 2: Viewing a Statistics Archive File on page 420 • Example 3: Viewing All Statistics of a Specified Instance ID on page 421 • Example 4: Viewing All Statistics of a Specified Instance ID and Stat ID on page 421 • Example 5: Viewing One Statistic of a Specified Instance ID and Stat ID on page 422 Syntax sqlf stats ([][:][.])* [-details] [-nofilter|-persec|-persample] [-prunezeros] [-starttime=