473,289 Members | 1,884 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes and contribute your articles to a community of 473,289 developers and data experts.

How does ShardingSphere’s Show processlist & Kill Work?

For those of you who often use databases, you may wonder:

1. How do I check what SQL is currently being executed by the database, and in what state?

2. How do I terminate abnormal SQL? For instance, if a SELECT statement used to query a table with massive data does not carry query conditions, it would drag down the performance of the entire database. This may push to want to terminate this abnormal SQL.

In response to the above issues, Apache ShardingSphere introduced functions such as Show processlist and Kill <processID>.
[IMG]https://miro.medium.com/max/720/1*xs4XXyTqJgCfZy9Y2aSV7Q@2x.png[/IMG]

1. Introduction

Show processlist: this command can display the list of SQL currently being executed by ShardingSphere and the execution progress of each SQL. If ShardingSphere is deployed in cluster mode, the Show processlist function aggregates the SQL running for all Proxy instances in the cluster and then displays the result, so you can always see all the SQL running at that moment.

Expand|Select|Wrap|Line Numbers
  1. mysql> show processlist \G;
  2. *************************** 1. row ***************************
  3.      Id: 82a67f254959e0a0807a00f3cd695d87
  4.    User: root
  5.    Host: 10.200.79.156
  6.      db: root
  7. Command: Execute
  8.    Time: 19
  9.   State: Executing 0/1
  10.    Info: update t_order set version = 456
  11. 1 row in set (0.24 sec)
Kill <processID>: This command is implemented based on Show processlist and can terminate the running SQL listed in the Show processlist.

Expand|Select|Wrap|Line Numbers
  1. mysql> kill 82a67f254959e0a0807a00f3cd695d87;
  2. Query OK, 0 rows affected (0.17 sec)
2. How do they work?
Now that you understand the functions of Show processlist and Kill <processID>, let's see how the two commands work. As the working principle behind Kill <processID> is similar to that of Show processlist, we'll focus on the interpretation of Show processlist.

2.1 How is SQL saved and destroyed?
Each SQL executed in ShardingSphere will generate an ExecutionGroupContext object. The object contains all the information about this SQL, among which there is an executionID field to ensure its uniqueness.

When ShardingSphere receives a SQL command, the GovernanceExecuteProcessReporter#report is called to store ExecutionGroupContext information into the cache of ConcurrentHashMap (currently only DML and DDL statements of MySQL are supported; other types of databases will be supported in later versions. Query statements are also classified into DML).

Expand|Select|Wrap|Line Numbers
  1. public final class GovernanceExecuteProcessReporter implements ExecuteProcessReporter {
  2.  
  3.     @Override
  4.     public void report(final QueryContext queryContext, final ExecutionGroupContext<? extends SQLExecutionUnit> executionGroupContext,
  5.                        final ExecuteProcessConstants constants, final EventBusContext eventBusContext) {
  6.         ExecuteProcessContext executeProcessContext = new ExecuteProcessContext(queryContext.getSql(), executionGroupContext, constants);
  7.         ShowProcessListManager.getInstance().putProcessContext(executeProcessContext.getExecutionID(), executeProcessContext);
  8.         ShowProcessListManager.getInstance().putProcessStatement(executeProcessContext.getExecutionID(), executeProcessContext.getProcessStatements());
  9.     }
  10. }
  11. @NoArgsConstructor(access = AccessLevel.PRIVATE)
  12. public final class ShowProcessListManager {
  13.  
  14.     private static final ShowProcessListManager INSTANCE = new ShowProcessListManager();
  15.  
  16.     @Getter
  17.     private final Map<String, ExecuteProcessContext> processContexts = new ConcurrentHashMap<>();
  18.  
  19.     @Getter
  20.     private final Map<String, Collection<Statement>> processStatements = new ConcurrentHashMap<>();
  21.  
  22.     public static ShowProcessListManager getInstance() {
  23.         return INSTANCE;
  24.     }
  25.  
  26.     public void putProcessContext(final String executionId, final ExecuteProcessContext processContext) {
  27.         processContexts.put(executionId, processContext);
  28.     }
  29.  
  30.     public void putProcessStatement(final String executionId, final Collection<Statement> statements) {
  31.         if (statements.isEmpty()) {
  32.             return;
  33.         }
  34.         processStatements.put(executionId, statements);
  35.     }
  36. }
As shown above, the ShowProcessListManager class has two cache Maps, namely processContexts and processStatements. The former stores the mapping between executionID and ExecuteProcessContext.

The latter contains the mapping between executionID and Statement objects that may generate multiple statements after the SQL is overwritten.

Every time ShardingSphere receives a SQL statement, the SQL information will be cached into the two Maps. After SQL is executed, the cache of Map will be deleted.

Expand|Select|Wrap|Line Numbers
  1. @RequiredArgsConstructor
  2. public final class ProxyJDBCExecutor {
  3.  
  4.     private final String type;
  5.  
  6.     private final ConnectionSession connectionSession;
  7.  
  8.     private final JDBCDatabaseCommunicationEngine databaseCommunicationEngine;
  9.  
  10.     private final JDBCExecutor jdbcExecutor;
  11.  
  12.     public List<ExecuteResult> execute(final QueryContext queryContext, final ExecutionGroupContext<JDBCExecutionUnit> executionGroupContext,
  13.                                        final boolean isReturnGeneratedKeys, final boolean isExceptionThrown) throws SQLException {
  14.         try {
  15.             MetaDataContexts metaDataContexts = ProxyContext.getInstance().getContextManager().getMetaDataContexts();
  16.             EventBusContext eventBusContext = ProxyContext.getInstance().getContextManager().getInstanceContext().getEventBusContext();
  17.             ShardingSphereDatabase database = metaDataContexts.getMetaData().getDatabase(connectionSession.getDatabaseName());
  18.             DatabaseType protocolType = database.getProtocolType();
  19.             DatabaseType databaseType = database.getResource().getDatabaseType();
  20.             ExecuteProcessEngine.initialize(queryContext, executionGroupContext, eventBusContext);
  21.             SQLStatementContext<?> context = queryContext.getSqlStatementContext();
  22.             List<ExecuteResult> result = jdbcExecutor.execute(executionGroupContext,
  23.                     ProxyJDBCExecutorCallbackFactory.newInstance(type, protocolType, databaseType, context.getSqlStatement(), databaseCommunicationEngine, isReturnGeneratedKeys, isExceptionThrown,
  24.                             true),
  25.                     ProxyJDBCExecutorCallbackFactory.newInstance(type, protocolType, databaseType, context.getSqlStatement(), databaseCommunicationEngine, isReturnGeneratedKeys, isExceptionThrown,
  26.                             false));
  27.             ExecuteProcessEngine.finish(executionGroupContext.getExecutionID(), eventBusContext);
  28.             return result;
  29.         } finally {
  30.             ExecuteProcessEngine.clean();
  31.         }
  32.     }
As shown above, ExecuteProcessEngine.initialize(queryContext, executionGroupContext, eventBusContext); will store the SQL information in the two cache Maps. Finally, ExecuteProcessEngine.clean(); in the code block will clear up the Map in the cache.

The SQL shown in the Show processlist was obtained from processContexts. But this Map is just a local cache. If ShardingSphere is deployed in cluster mode, how does Show processlist obtain SQL running on other machines in the cluster? Let's see how ShardingSphere handles it.

2.2 How does Show processlist work?
When ShardingSphere receives the Show process command, it is sent to the executor ShowProcessListExecutor#execute for processing. The implementation of the getQueryResult() is the focus.

Expand|Select|Wrap|Line Numbers
  1. public final class ShowProcessListExecutor implements DatabaseAdminQueryExecutor {
  2.  
  3.     private Collection<String> batchProcessContexts;
  4.  
  5.     @Getter
  6.     private QueryResultMetaData queryResultMetaData;
  7.  
  8.     @Getter
  9.     private MergedResult mergedResult;
  10.  
  11.     public ShowProcessListExecutor() {
  12.         ProxyContext.getInstance().getContextManager().getInstanceContext().getEventBusContext().register(this);
  13.     }
  14.  
  15.     @Subscribe
  16.     public void receiveProcessListData(final ShowProcessListResponseEvent event) {
  17.         batchProcessContexts = event.getBatchProcessContexts();
  18.     }
  19.  
  20.     @Override
  21.     public void execute(final ConnectionSession connectionSession) {
  22.         queryResultMetaData = createQueryResultMetaData();
  23.         mergedResult = new TransparentMergedResult(getQueryResult());
  24.     }
  25.  
  26.     private QueryResult getQueryResult() {
  27.         ProxyContext.getInstance().getContextManager().getInstanceContext().getEventBusContext().post(new ShowProcessListRequestEvent());
  28.         if (null == batchProcessContexts || batchProcessContexts.isEmpty()) {
  29.             return new RawMemoryQueryResult(queryResultMetaData, Collections.emptyList());
  30.         }
  31.         Collection<YamlExecuteProcessContext> processContexts = new LinkedList<>();
  32.         for (String each : batchProcessContexts) {
  33.             processContexts.addAll(YamlEngine.unmarshal(each, BatchYamlExecuteProcessContext.class).getContexts());
  34.         }
  35.         List<MemoryQueryResultDataRow> rows = processContexts.stream().map(processContext -> {
  36.             List<Object> rowValues = new ArrayList<>(8);
  37.             rowValues.add(processContext.getExecutionID());
  38.             rowValues.add(processContext.getUsername());
  39.             rowValues.add(processContext.getHostname());
  40.             rowValues.add(processContext.getDatabaseName());
  41.             rowValues.add("Execute");
  42.             rowValues.add(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - processContext.getStartTimeMillis()));
  43.             int processDoneCount = processContext.getUnitStatuses().stream().map(each -> ExecuteProcessConstants.EXECUTE_STATUS_DONE == each.getStatus() ? 1 : 0).reduce(0, Integer::sum);
  44.             String statePrefix = "Executing ";
  45.             rowValues.add(statePrefix + processDoneCount + "/" + processContext.getUnitStatuses().size());
  46.             String sql = processContext.getSql();
  47.             if (null != sql && sql.length() > 100) {
  48.                 sql = sql.substring(0, 100);
  49.             }
  50.             rowValues.add(null != sql ? sql : "");
  51.             return new MemoryQueryResultDataRow(rowValues);
  52.         }).collect(Collectors.toList());
  53.         return new RawMemoryQueryResult(queryResultMetaData, rows);
  54.     }
  55.  
  56.     private QueryResultMetaData createQueryResultMetaData() {
  57.         List<RawQueryResultColumnMetaData> columns = new ArrayList<>();
  58.         columns.add(new RawQueryResultColumnMetaData("", "Id", "Id", Types.VARCHAR, "VARCHAR", 20, 0));
  59.         columns.add(new RawQueryResultColumnMetaData("", "User", "User", Types.VARCHAR, "VARCHAR", 20, 0));
  60.         columns.add(new RawQueryResultColumnMetaData("", "Host", "Host", Types.VARCHAR, "VARCHAR", 64, 0));
  61.         columns.add(new RawQueryResultColumnMetaData("", "db", "db", Types.VARCHAR, "VARCHAR", 64, 0));
  62.         columns.add(new RawQueryResultColumnMetaData("", "Command", "Command", Types.VARCHAR, "VARCHAR", 64, 0));
  63.         columns.add(new RawQueryResultColumnMetaData("", "Time", "Time", Types.VARCHAR, "VARCHAR", 10, 0));
  64.         columns.add(new RawQueryResultColumnMetaData("", "State", "State", Types.VARCHAR, "VARCHAR", 64, 0));
  65.         columns.add(new RawQueryResultColumnMetaData("", "Info", "Info", Types.VARCHAR, "VARCHAR", 120, 0));
  66.         return new RawQueryResultMetaData(columns);
  67.     }
  68. }
You’ll use the guava package's EventBus function, which is an information publish/subscribe database that is an elegant implementation of the Observer pattern. EventBus decouples classes from each other, and you'll find out more about it below.

getQueryResult() method will post ShowProcessListRequestEvent. ProcessRegistrySubscriber#loadShowProcessListData uses the @Subscribe annotations to subscribe to the event.

This method is the core to implementing Show processlist. Next, we'll introduce specific procedures of this method.

Expand|Select|Wrap|Line Numbers
  1. public final class ProcessRegistrySubscriber {    
  2.     @Subscribe
  3.     public void loadShowProcessListData(final ShowProcessListRequestEvent event) {
  4.         String processListId = new UUID(ThreadLocalRandom.current().nextLong(), ThreadLocalRandom.current().nextLong()).toString().replace("-", "");
  5.         boolean triggerIsComplete = false;
  6.         // 1. Obtain the Process List path of all existing proxy nodes in cluster mode
  7.         Collection<String> triggerPaths = getTriggerPaths(processListId);
  8.         try {
  9.             // 2. Iterate through the path and write an empty string to the node, to trigger the node monitoring.
  10.             triggerPaths.forEach(each -> repository.persist(each, ""));
  11.             // 3. Lock and wait 5 seconds for each node to write the information of currently running SQL to the persistence layer. 
  12.             triggerIsComplete = waitAllNodeDataReady(processListId, triggerPaths);
  13.             // 4. Fetch and aggregate the data written by each proxy node from the persistence layer. Then EventBus will post a ShowProcessListResponseEvent command, which means the operation is completed.
  14.             sendShowProcessList(processListId);
  15.         } finally {
  16.             // 5. Delete resources
  17.             repository.delete(ProcessNode.getProcessListIdPath(processListId));
  18.             if (!triggerIsComplete) {
  19.                 triggerPaths.forEach(repository::delete);
  20.             }
  21.         }
  22.     }
  23. }
It contains five steps and steps 2 & 3 are the focus.

2.2.1 Step 2: the cluster obtains the data implementation
In this step, an empty string will be written to the node /nodes/compute_nodes/process_trigger/<instanceId>:<processlistId>, which will trigger ShardingSphere's monitoring logic.

When ShardingSphere is started, the persistence layer will watch to monitor a series of path changes, such as the addition, deletion, and modification operations of the path /nodes/compute_nodes.

However, monitoring is an asynchronous process and the main thread does not block, so step 3 is required to lock and wait for each ShardingSphere node to write its currently running SQL information into the persistence layer.

Let's take a look at how the ShardingSphere handles the monitoring logic.

Expand|Select|Wrap|Line Numbers
  1. public final class ComputeNodeStateChangedWatcher implements GovernanceWatcher<GovernanceEvent> {
  2.  
  3.     @Override
  4.     public Collection<String> getWatchingKeys(final String databaseName) {
  5.         return Collections.singleton(ComputeNode.getComputeNodePath());
  6.     }
  7.  
  8.     @Override
  9.     public Collection<Type> getWatchingTypes() {
  10.         return Arrays.asList(Type.ADDED, Type.UPDATED, Type.DELETED);
  11.     }
  12.  
  13.     @SuppressWarnings("unchecked")
  14.     @Override
  15.     public Optional<GovernanceEvent> createGovernanceEvent(final DataChangedEvent event) {
  16.         String instanceId = ComputeNode.getInstanceIdByComputeNode(event.getKey());
  17.         if (!Strings.isNullOrEmpty(instanceId)) {
  18.             ...
  19.         } else if (event.getKey().startsWith(ComputeNode.getOnlineInstanceNodePath())) {
  20.             return createInstanceEvent(event);
  21.             // show processlist
  22.         } else if (event.getKey().startsWith(ComputeNode.getProcessTriggerNodePatch())) {
  23.             return createShowProcessListTriggerEvent(event);
  24.             // kill processlistId
  25.         } else if (event.getKey().startsWith(ComputeNode.getProcessKillNodePatch())) {
  26.             return createKillProcessListIdEvent(event);
  27.         }
  28.         return Optional.empty();
  29.     }
  30.  
  31.  
  32.     private Optional<GovernanceEvent> createShowProcessListTriggerEvent(final DataChangedEvent event) {
  33.         Matcher matcher = getShowProcessTriggerMatcher(event);
  34.         if (!matcher.find()) {
  35.             return Optional.empty();
  36.         }
  37.         if (Type.ADDED == event.getType()) {
  38.             return Optional.of(new ShowProcessListTriggerEvent(matcher.group(1), matcher.group(2)));
  39.         }
  40.         if (Type.DELETED == event.getType()) {
  41.             return Optional.of(new ShowProcessListUnitCompleteEvent(matcher.group(2)));
  42.         }
  43.         return Optional.empty();
  44.     }
  45. }
After ComputeNodeStateChangedWatcher#createGovernanceEve nt monitored the information, it would distinguish which event to create according to the path.

As shown in the above code, it is a new node, so ShowProcessListTriggerEvent will be posted. As each ShardingSphere instance will monitor /nodes/compute_nodes, each instance will process ShowProcessListTriggerEvent.

In this case, single-machine processing is transformed into cluster processing. Let's look at how ShardingSphere handles it.

Expand|Select|Wrap|Line Numbers
  1. public final class ClusterContextManagerCoordinator {
  2.     @Subscribe
  3.     public synchronized void triggerShowProcessList(final ShowProcessListTriggerEvent event) {
  4.         if (!event.getInstanceId().equals(contextManager.getInstanceContext().getInstance().getMetaData().getId())) {
  5.             return;
  6.         }
  7.         Collection<ExecuteProcessContext> processContexts = ShowProcessListManager.getInstance().getAllProcessContext();
  8.         if (!processContexts.isEmpty()) {
  9.             registryCenter.getRepository().persist(ProcessNode.getProcessListInstancePath(event.getProcessListId(), event.getInstanceId()),
  10.                     YamlEngine.marshal(new BatchYamlExecuteProcessContext(processContexts)));
  11.         }
  12.         registryCenter.getRepository().delete(ComputeNode.getProcessTriggerInstanceIdNodePath(event.getInstanceId(), event.getProcessListId()));
  13.     }
  14. }
ClusterContextManagerCoordinator#triggerShowProces sList will subscribe to ShowProcessListTriggerEvent, in which processContext data is processed by itself. ShowProcessListManager.getInstance().getAllProcess Context() retrieves the processContext that is currently running (here the data refers to the SQL information that ShardingSphere stores in the Map before each SQL execution, which is described at the beginning of the article) and transfers it to the persistence layer. If the /nodes/compute_nodes/process_trigger/<instanceId>:<processlistId> node is deleted, the processing is completed.

When you delete the node, monitoring will also be triggered and ShowProcessListUnitCompleteEvent will be posted. This event will finally awake the pending lock.

Expand|Select|Wrap|Line Numbers
  1. public final class ClusterContextManagerCoordinator {
  2.  
  3.     @Subscribe
  4.     public synchronized void completeUnitShowProcessList(final ShowProcessListUnitCompleteEvent event) {
  5.         ShowProcessListSimpleLock simpleLock = ShowProcessListManager.getInstance().getLocks().get(event.getProcessListId());
  6.         if (null != simpleLock) {
  7.             simpleLock.doNotify();
  8.         }
  9.     }
  10. }
2.2.2 Step 3: lock and wait for the data implementation
ShardingSphere uses the isReady(Paths) method to determine whether all instances have been processed. It returns true only when all instances have been processed.

There is a maximum waiting time of 5 seconds for data processing. If the processing is not completed in 5 seconds, then false is returned.

Expand|Select|Wrap|Line Numbers
  1. public final class ClusterContextManagerCoordinator {
  2.  
  3.     @Subscribe
  4.     public synchronized void completeUnitShowProcessList(final ShowProcessListUnitCompleteEvent event) {
  5.         ShowProcessListSimpleLock simpleLock = ShowProcessListManager.getInstance().getLocks().get(event.getProcessListId());
  6.         if (null != simpleLock) {
  7.             simpleLock.doNotify();
  8.         }
  9.     }
  10. }
2.2.3 Aggregate the processList data and return it
After each instance processed the data, the instance that received the Show processlist command needs to aggregate the data and then display the result.

Expand|Select|Wrap|Line Numbers
  1. public final class ProcessRegistrySubscriber {  
  2.  
  3.     private void sendShowProcessList(final String processListId) {
  4.         List<String> childrenKeys = repository.getChildrenKeys(ProcessNode.getProcessListIdPath(processListId));
  5.         Collection<String> batchProcessContexts = new LinkedList<>();
  6.         for (String each : childrenKeys) {
  7.             batchProcessContexts.add(repository.get(ProcessNode.getProcessListInstancePath(processListId, each)));
  8.         }
  9.         eventBusContext.post(new ShowProcessListResponseEvent(batchProcessContexts));
  10.     }
  11. }
ProcessRegistrySubscriber#sendShowProcessList will aggregate the running SQL data into batchProcessContexts, and then post ShowProcessListResponseEvent.

This event will be consumed by ShowProcessListExecutor#receiveProcessListData, and the getQueryResult() method will proceed to show the queryResult.

So far, we’ve completed the execution process of Show processlist command.

2.3 How does Kill <processId> work?

Kill <processId> shares a similar logic with Show processlist, that is to combine EventBus with the watch mechanism.

Since we do not know which SQL the processId belongs to, it is also necessary to add empty nodes for each instance.

Through the watch mechanism, each ShardingSphere instance watches to the new node and checks whether the processId key is in the cache Map. If yes, fetch the value corresponding to the key.

The value is a Collection<Statement> collection. Then you only have to iterate through the Statement collection and call statement.cancel() in turn. The underlying layer is java.sql.Statement#cancel() method called to cancel SQL execution.

3. Conclusion

Currently, Apache ShardingSphere can only implement the Show processlist and Kill <processId> functions for MySQL dialects.

Once you get to know how they work, and if you’re interested, you‘re welcome to participate in the development of related functions. Our community is very open and anyone who is interested in contributing to open source code is welcome.

Relevant Links:
Apache ShardingSphere Official Website

Apache ShardingSphere GitHub

Apache ShardingSphere Slack Channel

Author
Xu Yang, a middleware R&D engineer at Servyou Group. Responsible for the table and database sharding with massive data. An open source enthusiast and ShardingSphere contributor. Currently, he’s interested in developing the kernel module of the ShardingSphere project.
Sep 27 '22 #1
0 4630

Sign in to post your reply or Sign up for a free account.

Similar topics

0
by: Mechain Marc | last post by:
I would like to know (if possible, there is no explanation in the = documentation) the exact meanning of the column "time" in the "show = processlist" command. Why is it sometime so hight ?...
2
by: Sam | last post by:
Is there a way to filter 'show processlist'? like show processlist where Host rlike "abc" Thanks, Sam
6
by: greenflame | last post by:
I have been working for some time on a script that will show a matrix with the elements aligned on the right for sometime and finally got it to work. Then I did some patching up and ran the script...
1
by: Georg Scholz | last post by:
Hello, The class "Control" contains a documented Property "ControlType". So for example, in a form, you can write code like this: Dim c as control set c = me.Controls("textbox1") if...
4
by: Charts | last post by:
I have a C# console application and I need pop up a Messagebox. However the IntelliSense does not show for using System.Windows.Forms; So, the application does not recognize the MessageBox. Please...
5
by: D Witherspoon | last post by:
What is happening is that I have a class (ClassA) that inherits a class (ClassB) which inherits System.Net.Mail.MailMessage Project 1 references Project 2, Project 2 references Project 3. ...
0
by: teju | last post by:
Hi, I need to get the information about show processlist in an query so i can display in ASP .Iam successfull in getting the whole table results using and displaying but if i need to use where...
11
by: andrewdb | last post by:
I have been working with a database that was already created by somebody else, who now no longer works here, so I cant ask any questions. None the less, there is a table 'Ascertainment' which...
0
by: Hetal | last post by:
We recently upgraded to VS 2008 and for some reason, the environment does not show "Start Page" in full screen mode even when setting in Environment -Startup is set to "Show Start Page". It does...
6
by: lburleigh | last post by:
Hello, So I have a worksheet on access with my VBA code along with a form and a table on access. All three of these are connected and work off of each other. My problem is that I have a value...
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: Aftab Ahmad | last post by:
Hello Experts! I have written a code in MS Access for a cmd called "WhatsApp Message" to open WhatsApp using that very code but the problem is that it gives a popup message everytime I clicked on...
0
by: Aftab Ahmad | last post by:
So, I have written a code for a cmd called "Send WhatsApp Message" to open and send WhatsApp messaage. The code is given below. Dim IE As Object Set IE =...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: marcoviolo | last post by:
Dear all, I would like to implement on my worksheet an vlookup dynamic , that consider a change of pivot excel via win32com, from an external excel (without open it) and save the new file into a...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.